你能解释/解决这些"通用约束"编译器错误吗?

and*_*ewz 3 generics protocols swift swift3

尝试声明一个协议时,我得到以下两个编译器错误associatedType- 不确定是什么generic constraint.

protocol Listener {
    associatedType ValueType
    func call(_ binding:Binding<ValueType>, value:ValueType)
}


class Binding<T> {
    var value:T?
    var listeners:[Listener] = [] // error 1: Protocol 'Listener' can only be used as a generic constraint because it has Self or associated type requirements
    func fire() {
        listeners.forEach { $0.call(self,value:self.value) } // error 2: Member 'call' cannot be used on value of protocol type 'Listener'; use a generic constraint instead
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 10

这是对协议的错误使用.协议相关类型由协议的实现者确定,而不是协议的用户.泛型由协议的用户确定.没有自动将协议包装到泛型中(该功能将被称为"存在容器",我们不知道它何时会出现).

[Listener]不是一个完整的类型.是什么ValueType

对于这种特殊情况,没有合理的理由.它只捕获一个功能.你应该只传递函数:

class Binding<T> {
    var value: T?
    var listeners:[(Binding<T>, T) -> ()] = []
    func fire() {
        if let value = value {
            listeners.forEach { $0(self, value) }
        }
    }

    init() {}
}
Run Code Online (Sandbox Code Playgroud)

如果您真的需要协议,可以将其提升为类型橡皮擦(AnyListener):

protocol Listener {
    associatedtype ValueType
    func call(_ binding:Binding<ValueType>, value:ValueType)
}

struct AnyListener<ValueType>: Listener {
    let _call: (Binding<ValueType>, ValueType) -> ()
    init<L: Listener>(_ listener: L) where L.ValueType == ValueType {
        _call = listener.call
    }
    func call(_ binding: Binding<ValueType>, value: ValueType) {
        _call(binding, value)
    }
}

class Binding<T> {
    var value:T?
    var listeners: [AnyListener<T>] = []
    func fire() {
        if let value = value {
            listeners.forEach { $0.call(self, value: value) }
        }
    }
}

let listener = ... some listener ....
binding.listeners.append(AnyListener(listener))
Run Code Online (Sandbox Code Playgroud)

或者你可以AnyListener进入一个更具体的结构并摆脱协议.但对于这么简单的情况,我通常会传递函数.

  • 很好的答案. (3认同)