swift - 你能解释/解决这些 'generic constraint' 编译器错误吗?

标签 swift generics swift3 protocols

当我尝试使用 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/

相关文章:

ios - 'NSInternalInconsistencyException',原因 : 'Couldn' t posix_spawn: error 13' Swift

swift - macOS - 使用 `Process` telnet 到一个 IP 地址并传递命令

java - java如何确定在类型删除过程中插入 "type cast"的位置

ios - 使用可解码和 JSON

ios - 字符串文字中的 Swift 特殊 Unicode 字符

generics - 有没有办法表达具有不同生命周期界限的 "same"泛型类型?

java - 要使用嵌套的通用集合或自定义中间类?

ios - 查找字符串数组的最长公共(public)子串

ios - 使用 AVFoundation 在 Swift 3.0 中扫描条形码或二维码

ios - Swift 3 使用 CKAsset 将图像发送到 CloudKit