Using delegates on generic protocol

后端 未结 2 1779
半阙折子戏
半阙折子戏 2021-01-22 23:14

I have got this code:

protocol GenericProtocol: class {
    associatedtype type
    func funca(component: type)
}

class MyType {

    weak var delegate         


        
相关标签:
2条回答
  • 2021-01-22 23:40

    This is not possible to use generic protocols. Use concrete type or usual protocol instead. You have to declare concrete T outside of those abstractions

    For instance, this should work:

    class MyType<T> {
    
        weak var delegate: UsingGenericProtocol<T>? // First error
    
        var t: T
    
        init(t: T) {
            self.t = t
        }
    
        func finished() {
            delegate?.funca(component: t) // Second error
        }
    
    }
    class UsingGenericProtocol<T>: GenericProtocol {
        let myType: MyType<T>
        typealias type = T
    
        init(t: T) {
            myType = MyType<T>(t: t)
        }
    
        func funca(component: T) {
    
        }
    }
    
    let instance = UsingGenericProtocol<Int>(t: 0)
    
    0 讨论(0)
  • 2021-01-22 23:54

    The difference between generics and associated types is that generics are specified at instantiation, associated types during implementation. So you cannot use the protocol type as a concrete type because the associated type depends on the implementing type.

    However, there are a few workarounds:

    1) Use the type of the delegate as a generic type:

    class MyType<Delegate: GenericProtocol> {
        typealias T = Delegate.type
        ...
    }
    

    2) Use a common protocol on your delegate method instead of an associated type:

    protocol CommonProtocol { ... }
    
    protocol DelegateProtocol {
        func funca(component: CommonProtocol)
    }
    

    3) Use closures for type erasure (this is also done in the Swift Standard Library for the Sequence protocol with AnySequence<Element>)

    struct AnyGenericProtocol<GenericType>: GenericProtocol {
        typealias type = GenericType
        private let f: (GenericType) -> ()
    
        init<G: GenericProtocol>(_ g: GenericProtocol) where G.type == GenericType {
            f = { component in
                g.funca(component: component)
            }
        }
    
        func funca(component: GenericType) {
            f(component)
        }
    }
    
    class MyType<T> {
        var delegate: AnyGenericProtocol<T>
        ...
    }
    
    0 讨论(0)
提交回复
热议问题