我正在使用Swift并尝试制作一些集合对象。这些集合对象具有支持Dictionary
以保存自定义对象。例如,对象可能是Cat
类型,集合对象的类型为Cats
。 Cats
将包含一个包含Cat
类型值的私有字典。我有其他类型也需要相应的集合(每个集合类型具有它所拥有的类型的特定逻辑)。
我创建了一个协议,以确保每个集合都有一些共同的特征。这些常用功能和下标通常是支持字典的直通。这是协议:
protocol ObjectDictionaryProtocol {
// These are necessary for generics to work in protocols
typealias Key: Hashable
typealias Value
// MARK: - Properties
var count: Int { get }
var isEmpty: Bool { get }
var keys: LazyMapCollection<Dictionary<Key, Value>, Key> { get }
var values: LazyMapCollection<Dictionary<Key, Value>, Value> { get }
// MARK: - Subscripts
subscript(key: Key) -> Value? { get set }
}
当我真正将协议用作类型时,例如:
var objects: ObjectDictionaryProtocol
或
init(objs: ObjectDictionaryProtocol) {
...
}
我收到错误:
Protocol 'ObjectDictionaryProtocol' can only be used as a generic constraint because it has Self or associated type requirements
我已经四处搜索,看起来我Hashable
Key
符合的typealias
协议正在导致此问题。解决这个问题的最佳方法是什么?有没有办法更改协议,以便我不需要Hashable
,或者我是否需要在使用ObjectDictionaryProtocol
的类中执行某些操作?或者也许有一种更好的方法可以有效地进行子类化&#39;一个Swift Dictionary
(引用,因为我意识到Dictionary
struct
不能被子类化?)
答案 0 :(得分:0)
具有关联类型的协议不是类型,而是类型的模板。当指定协议的关联类型时,存在实际类型。因此ObjectDictionaryProtocol
&#39;变为&#39;指定时的类型:
ObjectDictionaryProtocol<String,Cat>
但上述内容无效Swift ......
所以你问过......&#39; [有]更好的方法来有效地分类&#39;一个快速字典&#39;。您可以使用extension
获得类似的内容:
class Cat {}
extension Dictionary where Value : Cat {
func voice (name: Key) {
if let _ = self[name] {
print ("\(name): Meow")
}
}
}
var someCats = Dictionary<String,Cat>()
someCats["Spot"] = Cat()
someCats.voice("Spot")
// Spot: Meow
或者您可能需要实际执行该协议。
class ObjectDiciontary<Key:Hashable, Value> : ObjectDictionaryProtocol {
var backingDictionary = Dictionary<Key,Value>()
// implement protocol
}
var object : ObjectDictionary<String,Cat> = ...
// ...
答案 1 :(得分:0)
原因是当您使用typealias
时,您有效地将Protocol
作为Protocol<T>
的通用协议。请耐心等待我,我将解释为什么以及如何解决它。
这里的问题是Apple决定使用typealias
关键字来定义关联类型。这在Swift 2.2(Xcode 7.3)中得到修复
您可以在https://github.com/apple/swift-evolution/blob/master/proposals/0011-replace-typealias-associated.md
它正在重命名为associatedtype
,这更有意义。
这意味着必须采用您的协议,并定义其相关类型。
在你的情况下,它看起来像
protocol ObjectDictionaryProtocol {
associatedtype Value
}
extension String : ObjectDictionaryProtocol {
associatedtype = Double
}
init可能看起来像
init<T : ObjectDictionaryProtocol>(objs: ObjectDictionaryProtocol)
或
init<T : ObjectDictionaryProtocol
where T.Value == Double>(objs: ObjectDictionaryProtocol)
现在typealias Key: Hashable
表示分配给Key
的任何类型都必须符合Hashable
这会给您一个String
不符合ObjectDictionaryProtocol
的错误,因为它无法满足要求。
protocol ObjectDictionaryProtocol {
associatedtype Value : FloatingPointType
}
extension String : ObjectDictionaryProtocol {
associatedtype = Int
}
Int
不是FloatingPointType
(但Double
是