Swift类型推断和具有关联类型的协议

时间:2018-02-06 18:51:01

标签: swift generics protocols swift-protocols

编辑:我无法理解为什么在AnyCacheable类中的where子句 - where U.CacheType == T中,Swift不会将该语句视为约束,而只是将T设置为{{1 }}。当事情不明显时,类型推断是最糟糕的:-)

我正在尝试按照here -

讨论Swift的类型擦除

具体如下代码:

U.CacheType

如果我创建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'的具体类型

Swift如何推断'T'的具体类型?从初始化程序 -

let cacheable:AnyCacheable = AnyCacheable<String>("Swift")

我可以看到Swift可以从初始化器参数推断出'U'的类型(在本例中是String类型)。在where子句'T'在rhs上。那么这个表达式如何评估为真呢?

1 个答案:

答案 0 :(得分:0)

String是一个Cacheable,它的decode返回一个String,因此它的关联类型CacheType必须是String。

使用String初始化AnyCacheable,根据需要可以使用Cacheable;所以它的U是String。但是U.CacheType是T.所以T是String。

要知道是这样,请将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>