EDIT: I can't understand why in the where clause below - where U.CacheType == T
in AnyCacheable class Swift doesn't treat that statement as a constraint but simply sets T to U.CacheType
. Type inference is the worst when things aren't readily apparent :-)
I am trying to follow Swift's Type erasure discussed here -
Specifically the code below:
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()
}
}
It works perfectly fine if I create a new instance of AnyCacheable
as -
let cacheable:AnyCacheable = AnyCacheable("Swift")
I don't need to explicitly specify the concrete type of 'T' like let cacheable:AnyCacheable = AnyCacheable<String>("Swift")
How does Swift infer the concrete type for 'T'? From the initializer -
init<U:Cacheable>(_ cacheable:U) where U.CacheType == T {
self._encode = cacheable.encode
self._decode = cacheable.decode
}
I can see that Swift can infer the type for 'U' from the initializer argument (in this case a String type). In the where clause 'T' is on rhs. So how does that expression evaluate to true?