我想初始化一个Set,其中包含与Hashable协议和自定义协议相对应的值.
我试过了 :
protocol CustomProtocol: Hashable {}
let set = Set<CustomProtocol>()
Run Code Online (Sandbox Code Playgroud)
但是Xcode抱怨道:
不支持使用'CustomProtocol'作为符合协议'Hashable'的具体类型
我怎样才能做到这一点?
提前致谢.
你不能做你想做的事情的直接原因是Hashable是一种通用协议.因此,它 - 或从中派生的协议 - 不能用作Set的元素类型.泛型类型只能用作另一个泛型中的约束.您会注意到Set<Hashable>
,即使set的元素类型必须符合 Hashable ,也不能声明其中任何一个.
最简单的方法是制作一组协议,而不是一组对象类型.例如,如果S是符合CustomProtocol的结构(因为它符合Hashable加上CustomProtocol所需的任何其他内容),则可以声明一组S.
例:
protocol CustomProtocol: Hashable {
}
func ==(lhs:S,rhs:S) -> Bool {
return lhs.name == rhs.name
}
struct S : CustomProtocol {
var name : String
var hashValue : Int { return name.hashValue }
}
let set = Set<S>()
Run Code Online (Sandbox Code Playgroud)
如果你想要解决的问题是你想要一个混合类型的集合,但它们在某种程度上是彼此相同的,那么协议扩展就解决了同样的问题,正如协议中的讨论所解释的那样 - 面向WWDC 2015的视频.
但是,只需要创建从NSObject派生的所有类型类就更简单了.当然,你仍然可以让它们采用一些辅助协议,但是这个集合不会被定义为一组协议而是NSObject.
在 Swift 3 中,一种解决方案是使用AnyHashable 结构。
例如,要创建一个 Observers/Observable 模式,我们可以这样做:
protocol Observer {
func observableDidSomething(_ observable: Observable)
}
class Observable {
private var observersSet: Set<AnyHashable> = []
private var observers: [Observer] {
return observersSet.flatMap { $0 as? Observer }
}
func add<O>(_ observer: O) where O : Observer, O : Hashable {
observersSet.insert(observer)
}
func remove<O>(_ observer: O) where O : Observer, O : Hashable {
observersSet.remove(observer)
}
// ...
private func doSomething() {
// do something ...
observers.forEach { $0.observableDidSomething(self) }
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我将Hashable
协议与我的协议分开Observer
。
归档时间: |
|
查看次数: |
3411 次 |
最近记录: |