我有这样的代码:
public class Metal {}
public protocol Vehicle<M> {
associatedtype M
var material: [M] { get set }
}
public protocol Tracktor: Vehicle where M == Metal {}
public protocol MetalTracktor: Tracktor {
var material: [Metal] { get set }
}
无法编译
var material: [Meta]
的第二个定义,错误:
无法使用协变类型“[Metal]”覆盖类型“[Self.M]”的可变属性“材料”
为什么?用
Tracktor
类型专门化 Metal
的正确方法是什么?
我认为
Tracktor
已经专门用于 Metal
类型,因此第一个和第二个定义最终是相同的,因此不应发生冲突。我错过了什么?
我知道第二个定义是多余的,但是Swift通常允许冗余定义。为什么在这种情况下不呢?
Tracktor
协议已经专业化Vehicle
。你已经做到了。
您可以为
Tracktor
编写一个实现,并使用 [Metal]
作为 material
的类型。
public class MyTracktor: Tracktor {
public var material: [Metal] = []
}
Swift 首先判断
MyTracktor
是否符合Vehicle
。它推断关联类型 M
是 Metal
。这隐式创建了一个 typealias
声明:
typealias M = Metal
现在
MyTracktor
满足Vehicle
的两个要求,因此符合它。 MyTracktor.M == Metal
也是如此,所以符合Tracktor
。
不允许在
var material: [Metal] { get set }
中写入 MetalTracktor
,因为在 MetalTracktor
的上下文中,M
和 Metal
是两种不同(尽管相关)的类型。 M
是在 Vehicle
中声明的关联类型,Metal
是在全局范围内声明的类类型。
将此与上面的
MyTracktor
类进行比较。在 MyTracktor
中,M
是 Metal
的 类型别名-
M
和 Metal
是同一类型。另一方面,where M == Metal
表示的是 Tracktor
的要求,而不是类型别名。
从技术上讲,Swift 可以设计得更智能,并允许您在
var material: [Metal] { get set }
中编写 MetalTracktor
,但这并不是很有用,因为您只需编写 var material: [M] { get set }
即可完成基本相同的操作。