sol*_*ell 35 swift swift-protocols
为什么以下代码会产生错误?
protocol ProtocolA {
var someProperty: ProtocolB { get }
}
protocol ProtocolB {}
class ConformsToB: ProtocolB {}
class SomeClass: ProtocolA { // Type 'SomeClass' does not conform to protocol 'ProtocolA'
var someProperty: ConformsToB
init(someProperty: ConformsToB) {
self.someProperty = someProperty
}
}
Run Code Online (Sandbox Code Playgroud)
这个类似问题的答案是有道理的.但是,在我的示例中,属性是get-only.为什么不能这样做?它是Swift的缺点,还是有一些合理的理由?
Ham*_*ish 40
没有真正的理由说明为什么这是不可能的,只读属性要求可以是协变的,因为ConformsToB
从属性中返回一个实例ProtocolB
是完全合法的.
Swift目前不支持它.为此,编译器必须在协议见证表和符合实现之间生成一个thunk,以便执行必要的类型转换.例如,一个ConformsToB
实例需要在一个存在容器中装箱 才能被输入(并且调用者无法做到这一点,因为它可能对所调用的实现一无所知).ProtocolB
但同样,编译器没有理由不能这样做.有一些错误报告打开了这个,这个特定于只读属性需求,这是一般的,其中Swift团队成员Slava Pestov说:
[...]我们希望在允许功能转换的每种情况下都使用协议见证和方法覆盖
因此,它确实看起来像Swift团队希望在未来的语言版本中实现的东西.
然而,正如@BallpointBen所说的那样,一个解决方法是使用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
}
}
Run Code Online (Sandbox Code Playgroud)
但这是非常不令人满意的,因为这意味着它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
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们基本上是为编译器编写thunk - 但它也不是特别好,因为它为API添加了一个不必要的属性.
归档时间: |
|
查看次数: |
1138 次 |
最近记录: |