當我向具有關聯型別的協議添加約束擴展時,swift 編譯器會忽略我的約束。
當我寫:
protocol Arr {
associatedtype Element
func node(_ at: Int) -> Element?
}
extension Arr where Element == String {
func node(_ at: Int) -> String? {
nil
}
}
struct Doo: Arr {
}
Xcode 成功構建,它認為我Doo的Element是String. 它忽略where Element == String約束。
當我寫:
protocol Arr {
associatedtype Element
func node(_ at: Int) -> Element?
}
extension Arr where Element == String {
func node(_ at: Int) -> Element? { // use Element
nil
}
}
struct Doo: Arr {
}
正如預期的那樣,Xcode 顯示錯誤。
這是 Xcode 錯誤還是 Swift 功能?
Xcode 版本: Version 13.1 (13A1030d)
迅捷版:
swift-driver version: 1.26.9 Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)
Target: arm64-apple-macosx12.0
uj5u.com熱心網友回復:
第二種情況的錯誤是因為 Xcode 無法推斷 Element 的型別。如果你指定它,一切都會編譯。
struct Doo: Arr {
typealias Element = String
}
uj5u.com熱心網友回復:
這里發生的是 Swift 很樂意滿足協議要求,如果它可以從背景關系中提取它們。
例如,假設擴展名不存在,Doo定義如下:
struct Doo: Arr {
func node(_ at: Int) -> String? {
nil
}
}
,Swift 編譯器會很高興地填充Element關聯的型別。
類似的事情發生在您的第一個代碼片段中,Doo符合Arr,并且編譯器會找到滿足所有協議要求的定義。Swift 不會忽略Element == String約束,因為它將它與Doo結構相關聯。
如果您以類似的方式添加第二個擴展,但對于另一種型別(Int例如),您將看到您收到預期的錯誤。發生這種情況是因為編譯器無法再推斷協議要求。
Swift 編譯器急切地從它可以到達的背景關系中進行盡可能多的推斷,大多數情況下會給出很好的結果,有時不會那么好(尤其是在使用閉包時),有時它會給出意想不到的結果(比如這個)。
如果您想確保編譯器推斷出您想要的型別,解決方案是顯式宣告所有涉及的型別。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/344328.html
