有沒有真正的原因,這不應該是可能的,一個只讀屬性要求可以是協變,從類型爲ProtocolB
屬性返回ConformsToB
實例是完全合法的。
Swift目前不支持它。爲此,編譯器必須在協議見證表和符合實現之間生成a thunk以執行必要的類型轉換。例如,一個ConformsToB
實例將需要盒裝in an existential container爲了被輸入爲ProtocolB
(並且調用者無法做到這一點,因爲它可能不知道被調用實現的任何內容)。
但是,再次,沒有理由爲什麼編譯器不應該能夠做到這一點。有多種錯誤報告在這個開放的,this one這是特定於只讀屬性的要求,this general one,其中斯拉瓦佩斯托夫,雨燕小組的成員,他說:
[...]我們要在允許功能轉換的每一種情況下,協議證人和方法覆蓋
因此它絕對看起來像Swift團隊希望在未來版本的語言中實現的東西。
然而在此同時,爲@BallpointBen says,一個解決方法是使用一個associatedtype
:
protocol ProtocolA {
// allow the conforming type to satisfy this with a concrete type
// that conforms to ProtocolB.
associatedtype SomeProperty : ProtocolB
var someProperty: SomeProperty { get }
}
protocol ProtocolB {}
class ConformsToB: ProtocolB {}
class SomeClass: ProtocolA {
// implicitly satisfy the associatedtype with ConformsToB.
var someProperty: ConformsToB
init(someProperty: ConformsToB) {
self.someProperty = someProperty
}
}
但是,這是相當不令人滿意,因爲它意味着ProtocolA
不再可用作類型(因爲它有associatedtype
要求)。它也改變協議所說的內容。它最初說,someProperty
可以返回任何是符合ProtocolB
- 現在它說的someProperty
涉及符合ProtocolB
只是一個特定具體類型的實現。
另一個解決方法是僅僅爲了滿足協議要求定義的虛擬財產:
protocol ProtocolA {
var someProperty: ProtocolB { get }
}
protocol ProtocolB {}
class ConformsToB: ProtocolB {}
class SomeClass: ProtocolA {
// dummy property to satisfy protocol conformance.
var someProperty: ProtocolB {
return actualSomeProperty
}
// the *actual* implementation of someProperty.
var actualSomeProperty: ConformsToB
init(someProperty: ConformsToB) {
self.actualSomeProperty = someProperty
}
}
這裏,我們基本上是寫形實轉換爲編譯器 - 但它也並不特別漂亮,因爲它向API添加了不必要的屬性。
感謝您的聯繫。這是不幸的,但很高興知道! – solidcell
如果你想要這種行爲,在'ProtocolA'中你應該有'associatedtype T:ProtocolB',然後聲明'var someProperty:T {get}' – BallpointBen
這將作爲解決方法在此期間,直到它(希望)是固定的,但我真的很猶豫要添加一個關聯類型,因爲這會將這些知識引發到對象圖的其餘部分,而這些對象圖很快就會失去控制。 – solidcell