protocol A {}
protocol B {
var a: A { get }
}
struct StructA: A {}
struct StructB {
var a: StructA
}
extension StructB: B {}
这会产生错误:
键入' StructB'不符合协议' B'
StructA
已符合协议A
,StructB
的属性a
返回StructA
类型。这似乎是一个协议B符合类型。
但为什么?
Swift版本为2.2的Xcode版本7.3
答案 0 :(得分:3)
为了更好地说明当前代码的问题,假设您有一个StructC : A
。
您的协议B
表示您可以将StructC
分配给a
(因为它符合A
) - 但StructB
表示您无法分配StructC
1}}到StructA
类型。因此StructB
不符合B
。
解决方案是将a
的类型从StructA
更改为A
as Rahul says,或者更好的是,您可以使用泛型。
使用泛型的好处是,一旦您使用给定的StructB
创建a
- 该属性的类型将由Swift推断,为您提供更好的类型安全性。例如,为其分配StructA
后,其类型将为StructA
。如果您为其分配StructC
,则其类型将为StructC
。
为此,我们只需向协议associatedtype
添加B
即可。这将定义一个“占位符”类型,然后我们可以在符合B
的类型中实现该类型。然后,我们可以在T
中定义通用类型StructB
,它将提供AType
的“实施” - 确保它符合A
。因此,我们现在可以自由地将StructA
或StructC
分配给a
,而不会失去类型安全性。
protocol A {}
protocol B {
// new associated type to hold the type of "a" which conforms to A
associatedtype AType:A
var a: AType { get }
}
struct StructA: A {}
struct StructC:A {}
// define the new generic T which conforms to A
struct StructB<T:A> {
// define the type of a as the generic T, which conforms to A (and thus conforms with the protocol)
var a : T
}
extension StructB: B {}
let s = StructB(a: StructA())
s.a // "a" is now of type StructA
let s1 = StructB(a: StructC())
s1.a // "a" is now of type StructC
答案 1 :(得分:2)
因为Swift是静态类型的,并且不依赖于动态调度。你可以做类似下面的事情。
import UIKit
protocol A {}
protocol B {
var a: A { get }
}
struct StructA: A {}
struct StructB {
var a: A = StructA()
}
extension StructB: B {}