[英]Swift - upcasting array of protocol to array of super protocol causes error
在Swift中,我注意到我可以上载一个符合协议的对象,比如说SubProtocol
到另一个协议SuperProtocol
,它是SubProtocol
的超级协议。 但是我不能对协议数组做同样的事情。 这是我在Playground中运行的示例代码:
protocol SuperProtocol {
}
protocol SubProtocol: SuperProtocol {
}
class MyObject: SubProtocol {
}
let value1: SubProtocol = MyObject()
let value2: SuperProtocol = value1 // No error here. Upcasting works.
let array1: [SubProtocol] = [MyObject()]
let array2: [SuperProtocol] = array1 // Error here "Cannot convert value of type '[SubProtocol]' to specified type '[SuperProtocol]'"
这似乎违反直觉,我想知道为什么不允许这样做。
原因与协议如何从类继承不同有关。
首先考虑协议可以具有默认实现 ,例如:
protocol MammalLocomotion {
func legs() -> Int
}
extension MammalLocomotion {
func legs () -> Int {
return 2
}
}
protocol CowLocomotion : MammalLocomotion {
}
extension CowLocomotion {
func legs () -> Int {
return 4
}
}
让我们创建符合以下协议的类:
class Mammal : MammalLocomotion {
}
class Cow : Mammal, CowLocomotion {
}
let mammal = Mammal()
let cow = Cow()
他们的legs()
方法可以像我们期望的那样响应:
mammal.legs() // 2
cow.legs() // 4
但是现在让我们把cow
Mammal
:
let cowAsMammal : Mammal = cow
cowAsMammal.legs() // 2
cow
有4条腿,但现在有2
条腿。 这是因为,对于协议,当前已知的类型确定使用哪种默认实现。 因此,强制转换数组不起作用-我认为原因是,数组强制转换更改其包含的对象的行为是意外的。
正如您所指出的,这是行不通的:
let farm : [CowLocomotion] = [Cow(), Cow(), Cow()]
let mammalFarm : [MammalLocomotion] = farm // doesn't work
如果需要,可以通过将数组映射到所需的协议来解决此限制:
let farm = [Cow(), Cow(), Cow()]
farm.forEach { print($0.legs()) } // prints 4, 4, 4
let mammalFarm = farm.map { $0 as MammalLocomotion }
mammalFarm.forEach { print($0.legs()) } // prints 2, 2, 2
有关协议如何继承的更多信息,请参见今年的WWDC 笔录中的“面向协议的Swift编程”会议。
尝试此代码-刚刚检查过,效果很好
let array2: [SuperProtocol] = array1.map { $0 as SuperProtocol }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.