简体   繁体   English

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

[英]Swift Type Inference and Protocols with Associated Types

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 . 编辑 :我不明白为什么在下面的where子句中-AnyCacheable类中的where U.CacheType == T Swift不会将该语句视为约束,而只是将T设置为U.CacheType Type inference is the worst when things aren't readily apparent :-) 当事情不那么明显时,类型推断是最糟糕的:-)


I am trying to follow Swift's Type erasure discussed here - 我正在尝试遵循此处讨论的Swift的Type擦除-

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 - 如果我将AnyCacheable的新实例创建为-

let cacheable:AnyCacheable = AnyCacheable("Swift")

I don't need to explicitly specify the concrete type of 'T' like let cacheable:AnyCacheable = AnyCacheable<String>("Swift") 我不需要显式指定'T'的具体类型,如let cacheable:AnyCacheable = AnyCacheable<String>("Swift")

How does Swift infer the concrete type for 'T'? Swift如何推断'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). 我可以看到Swift可以从初始化参数中推断出'U'的类型(在这种情况下为String类型)。 In the where clause 'T' is on rhs. 在where子句中,“ T”在rhs上。 So how does that expression evaluate to true? 那么该表达式如何评估为真?

String is a Cacheable and its decode returns a String, so its associated type CacheType must be String. String是可缓存的,并且其decode返回String,因此其关联类型CacheType必须为String。

AnyCacheable is initialized with a String, which is a Cacheable as required; AnyCacheable使用字符串初始化,该字符串是所需的Cacheable; so its U is String. 所以它的U是String But U.CacheType is T. So T is String. 但是U.CacheType是T。所以T是String。


To see that this is so, change the definition of String's adoption of Cacheable to this: 要看到是这样,请将String通过Cacheable的采用的定义更改为:

extension String:Cacheable {
    func decode(_ data:Data)->Int? {
        return 42
    }
    func encode()->Data? {
        return data(using: .utf8)
    }
}

Now compile your code and look to see what type you get in the line 现在编译您的代码,看一看得到的类型

let cacheable:AnyCacheable = AnyCacheable("Swift")

It is AnyCacheable<Int> . 它是AnyCacheable<Int>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM