当我尝试使用 associatedType
声明协议(protocol)时,我遇到了以下两个编译器错误 - 不确定什么是 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
}
}
最佳答案
这是对协议(protocol)的错误使用。协议(protocol)关联类型由协议(protocol)的实现者决定,而不是协议(protocol)的用户。泛型由协议(protocol)的用户决定。没有自动将协议(protocol)包装到泛型中(该功能将被称为“存在容器”,我们不知道它何时会出现)。
[Listener]
不是一个完整的类型。 ValueType
是什么?
对于这种特殊情况,没有理由需要协议(protocol)。它只捕获一个函数。你应该只传递函数:
class Binding<T> {
var value: T?
var listeners:[(Binding<T>, T) -> ()] = []
func fire() {
if let value = value {
listeners.forEach { $0(self, value) }
}
}
init() {}
}
如果你真的需要这个协议(protocol),你可以将它提升到类型橡皮擦(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))
或者您可以将 AnyListener
变成一个更具体的结构并摆脱协议(protocol)。但对于这种简单的情况,我通常会传递函数。
关于swift - 你能解释/解决这些 'generic constraint' 编译器错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46433631/