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进入一个更具体的结构并摆脱协议.但对于这么简单的情况,我通常会传递函数.