I have problem to write the code that puts objects into the observers
array. The objects implement the Observer
protocol. I would like to link the ValueType
with the generic type T
of the Subject
. Here is the code that shows what I want to do:
protocol Observer {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers = Array<Observer>()
mutating func attach(observer: Observer) {
observers.append(observer)
}
func notyfi(value: T) {
for observer in observers {
observer.update(value: value)
}
}
}
CodePudding user response:
If your deployment target is at least a late 2022 release (iOS 16, macOS 13, etc.), you can use a constrained existential:
protocol Observer<ValueType> {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers = Array<any Observer<T>>()
mutating func attach(observer: any Observer<T>) {
observers.append(observer)
}
func notify(value: T) {
for observer in observers {
observer.update(value: value)
}
}
}
If your deployment target is earlier, the Swift runtime doesn't support constrained existentials. (From SE-0353: “It is worth noting that this feature requires revisions to the Swift runtime and ABI that are not backwards-compatible nor backwards-deployable to existing OS releases.”) But you can use closures instead:
protocol Observer<ValueType> {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers: [(T) -> Void] = []
mutating func attach<O: Observer>(observer: O)
where O.ValueType == T
{
observers.append { observer.update(value: $0) }
}
func notify(value: T) {
for observer in observers {
observer(value)
}
}
}
CodePudding user response:
Why don't you use the Observer
as the generic parameter?
struct Subject<O: Observer> {
typealias T = O.ValueType
private var observers = Array<O>()
mutating func attach(observer: O) {
observers.append(observer)
}
func notyfi(value: T) {
for observer in observers {
observer.update(value: value)
}
}
}