我想用Hashable協議和自定義協議對應的值初始化Set。在Swift中設置和協議
我想:
protocol CustomProtocol: Hashable {}
let set = Set<CustomProtocol>()
但Xcode的抱怨:
使用 'CustomProtocol' 作爲具體類型符合協議 '哈希的' 不支持
如何我做到了嗎?
在此先感謝。
我想用Hashable協議和自定義協議對應的值初始化Set。在Swift中設置和協議
我想:
protocol CustomProtocol: Hashable {}
let set = Set<CustomProtocol>()
但Xcode的抱怨:
使用 'CustomProtocol' 作爲具體類型符合協議 '哈希的' 不支持
如何我做到了嗎?
在此先感謝。
爲什麼你不能做你想做的事情的直接原因是Hashable是一個通用的協議。因此它或者從它派生的協議不能用作Set的元素類型。泛型類型只能用作另一個泛型中的約束。你會注意到,即使一個集合的元素類型必須符合到Hashable,你也不能聲明Set<Hashable>
。
最簡單的方法是,不是一組協議,而是一組對象類型。例如,如果S是符合CustomProtocol(因爲它符合哈希的加任何其他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>()
如果你的問題試圖解決的問題是,您希望收集的混合類型在某種程度上彼此相等,然後這就是通過協議擴展解決的相同問題,正如面向協議的WWDC 2015視頻中的討論所解釋的那樣。
但是,只是讓所有從NSObject派生出來的類型類更簡單。當然,您仍然可以讓它們採用一些輔助協議,但該集不會被定義爲該協議的集合,而是NSObject的集合。
在Swift 3中,一種解決方案是使用AnyHashable structure。
例如,創建一個觀察員/可觀察的模式,我們可以這樣做:
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) }
}
}
請注意,我從我的協議Observer
分開Hashable
協議。
已經需要符合Hashable的對象。 – Abizern
如果CustomProtocol不符合Hashable,則Xcode會抱怨CustomProtocol不符合它。看起來我錯過了一些東西。 –