编辑:我不明白为什么在下面的 where 子句中 - where U.CacheType == T
在 AnyCacheable 类中,Swift 不会将该语句视为约束,而只是将 T 设置为 U.CacheType
。当事情不明显时,类型推断是最糟糕的:-)
我正在尝试遵循讨论的 Swift 类型删除 here -
具体代码如下:
protocol Cacheable {
associatedtype CacheType
func decode(_ data:Data) ->CacheType?
func encode()->Data?
}
extension String:Cacheable {
func decode(_ data:Data)->String? {
let string = String(data: data, encoding: .utf8)
return string
}
func encode()->Data? {
return data(using: .utf8)
}
}
class AnyCacheable<T>:Cacheable {
private let _encode:()->Data?
private let _decode:(_ data:Data)->T?
init<U:Cacheable>(_ cacheable:U) where U.CacheType == T {
self._encode = cacheable.encode
self._decode = cacheable.decode
}
func decode(_ data:Data)->T? {
return _decode(data)
}
func encode() -> Data? {
return _encode()
}
}
如果我创建 AnyCacheable
的新实例,它工作得很好。作为-
let cacheable:AnyCacheable = AnyCacheable("Swift")
我不需要显式指定“T”的具体类型,如 let cacheable:AnyCacheable = AnyCacheable<String>("Swift")
Swift 如何推断“T”的具体类型?来自初始化器 -
init<U:Cacheable>(_ cacheable:U) where U.CacheType == T {
self._encode = cacheable.encode
self._decode = cacheable.decode
}
我可以看到 Swift 可以从初始化参数(在本例中为 String 类型)推断出“U”的类型。在 where 子句中,'T' 位于 rhs 上。那么该表达式如何计算为 true 呢?
最佳答案
字符串是可缓存的,其 decode
返回一个String,所以它的关联类型CacheType必须是String。
AnyCacheable用String初始化,根据需要是一个Cacheable;所以它的 U 是 String。但是U.CacheType
是 T。所以 T 是字符串。
要看到是这样,将String采用Cacheable的定义改为这样:
extension String:Cacheable {
func decode(_ data:Data)->Int? {
return 42
}
func encode()->Data? {
return data(using: .utf8)
}
}
现在编译您的代码并查看该行中得到的类型
let cacheable:AnyCacheable = AnyCacheable("Swift")
是AnyCacheable<Int>
.
关于Swift 类型推断和关联类型协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48649946/