【问题标题】:Using delegates on generic protocol在通用协议上使用委托
【发布时间】:2018-04-28 11:20:52
【问题描述】:

我有这个代码:

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

class MyType<T> {

    weak var delegate: GenericProtocol? // First error

    var t: T

    init(t: T) {
        self.t = t
    }

    func finished() {
        delegate?.funca(component: t) // Second error
    }

}

class UsingGenericProtocol: GenericProtocol {

    let myType: MyType<Int>
    typealias type = Int

    init() {
        myType = MyType<Int>(t: 0)
    }

    func funca(component: Int) {

    }

}

我想使用具有给定类型的委托。代码无法编译,因为我收到了这个错误:

Protocol 'GenericProtocol' 只能用作通用约束 因为它有 Self 或关联的类型要求

还有:

成员 'funca' 不能用于协议类型的值 '通用协议';改用通用约束

我可以通过从协议中删除类型,将其设为 Any 然后将其转换为正确的类型来省略此错误,但我认为泛型应该涵盖此问题。有什么办法可以编译这段代码吗?谢谢。

【问题讨论】:

标签: swift generics


【解决方案1】:

泛型和关联类型的区别在于泛型是在实例化时指定的,关联类型是在实现过程中指定的。所以你不能将协议类型用作具体类型,因为关联类型取决于实现类型。

但是,有一些解决方法:

1) 使用委托的类型作为泛型类型:

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

2) 在委托方法上使用通用协议而不是关联类型:

protocol CommonProtocol { ... }

protocol DelegateProtocol {
    func funca(component: CommonProtocol)
}

3) 使用闭包进行类型擦除(这也在 Swift 标准库中为Sequence 协议和AnySequence&lt;Element&gt; 完成)

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>
    ...
}

【讨论】:

    【解决方案2】:

    这是不可能使用通用协议的。请改用具体类型或常用协议。您必须在这些抽象之外声明具体的 T

    例如,这应该可以:

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-06
      • 1970-01-01
      • 2017-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多