Swift - 将协议数组上传到超级协议数组会导致错误

时间:2015-10-12 21:37:00

标签: arrays swift protocols upcasting

在Swift中,我注意到我可以向一个符合协议的对象进行upcast,让我们说SubProtocol到另一个叫SuperProtocol的协议,这是{{1}的超级协议}}。但我不能对协议数组做同样的事情。这是我在Playground中运行的示例代码:

SubProtocol

这似乎违反直觉,我想知道为什么不允许这样做。

2 个答案:

答案 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 }