繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM