简体   繁体   中英

Extend Array of generic objects in swift

I would like to write an extension to array of generic type in swift. This is how I tried to do this:

class Observer<Type> {
    private(set) weak var observer: AnyObject?
    private var listener: (_ newValue: Type) -> ()

    init(observer: AnyObject, listener: @escaping (_ newValue: Type) -> ()) {
        self.observer = observer
        self.listener = listener
    }
}

extension Collection where Iterator.Element == Observer<Type> {
    func foo<Type>(value: Type) {
        forEach { $0.listener(value) }
    }
}

I would like to be able to execute function with parameter of this generic type. Is there any way to write such extension? Later this would look something like this:

let observers = [Observer<Int>]()
observers.forEach { $0.foo(4) }

Your example doesn't match your implementation. What is foo ? And how does it relate to a ? I'm going to make a guess here that you mean this to be:

extension Collection where Iterator.Element == Observer<Type> {
    func foo<Type>(value: Type) {
        forEach { $0.listener(value) }
    }
}

And then later:

let observers = [Observer<Int>]()
observers.foo(value: 4)

You cannot attach an extension to a Collection based on a specific Element. That's a restriction on extensions that has nothing to do with whether Observer is generic. You can't use == in the where clause. But you can use a protocol.

protocol Observing {
    associatedtype ObservingType

    var listener: (_ newValue: ObservingType) -> () { get }
}

Then mark Observer as Observing:

class Observer<ObservingType>: Observing {
    private(set) weak var observer: AnyObject?
    var listener: (_ newValue: ObservingType) -> ()

I've made two other changes. I swapped Type for ObservingType because Type is a keyword (so it's a bit confusing). Also, listener cannot be private unless the extension is also private.

OK, given that:

extension Collection where Iterator.Element: Observing {
    func foo(value: Iterator.Element.ObservingType) {
        forEach { $0.listener(value) }
    }
}

let observers = [Observer<Int>]()
observers.foo(value: 4)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM