Я хочу разработать общий протокол Swift для шаблона наблюдателя для использования с разными типами / классами. Проблема в том, что я не могу указать тип для метода notify()
наблюдателя.
Первоначально я пытался создать associatedtype
с моим Observer
протоколом.
protocol Observer {
associatedtype T
func notify(_ value: T)
}
protocol Observable {
var observers: [Observer] { get set }
func registerObserver(_ observer: Observer)
func unregisterObserver(_ observer: Observer)
}
Не работает (ошибка компиляции): error: protocol 'Observer' can only be used as a generic constraint because it has Self or associated type requirements
.
Поэтому я попытался использовать вместо этого общие методы:
protocol Observer {
func notify<T>(_ value: T)
}
protocol Observable {
associatedtype T
var observers: [Observer] { get set } // This is okay now
}
extension Observable {
// implement registerObserver()
// implement unregisterObserver()
func notifyObservers<T>(_ value: T) {
for observer in observers {
observer.notify(value)
}
}
}
Это прекрасно работает, но приводит к довольно интересному результату. Чтобы проверить это, я создал FooObserver
и FooObservable
:
class FooObserver: Observer {
func notify<T>(_ value: T) {
print(value)
}
}
class FooObservable: Observable {
typealias T = Int // For simplicity I set T to Int type
var observers: [Observer] = []
}
let a = FooObserver()
let b = FooObserver()
var c = FooObservable()
c.registerObserver(a)
c.registerObserver(b)
c.notifyObservers("hello") // This works, but why?
Мне удалось успешно уведомить двух моих наблюдателей строкой «привет». Я предполагаю, что это связано со стиранием шрифта ...?
Итак, мой вопрос: как я могу реализовать шаблон наблюдателя общего типа, когда я могу быть уверен, что значение в notify()
имеет правильный тип?