在Swift中,我注意到我可以向一个符合协议的对象进行upcast,让我们说SubProtocol
到另一个叫SuperProtocol
的协议,这是{{1}的超级协议}}。但我不能对协议数组做同样的事情。这是我在Playground中运行的示例代码:
SubProtocol
这似乎违反直觉,我想知道为什么不允许这样做。
答案 0 :(得分:4)
原因与协议如何从类继承不同有关。
首先考虑协议可以具有默认实现,例如:
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会话 - transcript here。
答案 1 :(得分:0)
尝试此代码 - 只需选中,工作正常
let array2: [SuperProtocol] = array1.map { $0 as SuperProtocol }