Swift:将对象数组强制转换为子类型数组
假设我有一组动物,我想把它扔给一组猫。在这里,动物是猫采用的协议。我想要的东西像Swift:将对象数组强制转换为子类型数组,swift,Swift,假设我有一组动物,我想把它扔给一组猫。在这里,动物是猫采用的协议。我想要的东西像让猫:[猫]=动物一样![Cat]但是这个seg在编译时出错(顺便说一句,我同时使用Linux Swift 3和Mac Swift 2.2)。我的解决方法是只创建一个函数,该函数可以逐个地删除每个项并将其添加到新数组中(请参见下面的小示例)。它产生了期望的结果,但没有我想要的那么干净 我的问题是: 这完全是愚蠢的,而我只是错过了一个更简单的方法 如何在下面的函数中传递类型作为目标参数,而不是传递实例?(例如,我希望传
让猫:[猫]=动物一样![Cat]
但是这个seg在编译时出错(顺便说一句,我同时使用Linux Swift 3和Mac Swift 2.2)。我的解决方法是只创建一个函数,该函数可以逐个地删除每个项并将其添加到新数组中(请参见下面的小示例)。它产生了期望的结果,但没有我想要的那么干净
我的问题是:
protocol Animal: CustomStringConvertible
{
var species: String {get set}
var id: Int {get set}
}
extension Animal
{
var description: String
{
return "\(self.species):\(self.id)"
}
}
class Cat: Animal
{
var species = "felis catus"
var id: Int
init(id: Int)
{
self.id = id
}
}
func convertArray<T, U>(_ array: [T], _ target: U) -> [U]
{
var newArray = [U]()
for element in array
{
guard let newElement = element as? U else
{
print("downcast failed!")
return []
}
newArray.append(newElement)
}
return newArray
}
let animals: [Animal] = [Cat(id:1),Cat(id:2),Cat(id:3)]
print(animals)
print(animals.dynamicType)
// ERROR: cannot convert value of type '[Animal]' to specified type '[Cat]'
// let cats: [Cat] = animals
// ERROR: seg fault
// let cats: [Cat] = animals as! [Cat]
let cats: [Cat] = convertArray(animals, Cat(id:0))
print(cats)
print(cats.dynamicType)
协议动物:CustomStringConverable
{
变量种类:字符串{get set}
变量id:Int{get set}
}
扩展动物
{
变量说明:字符串
{
返回“\(self.species):\(self.id)”
}
}
类别猫:动物
{
var species=“猫科动物”
变量id:Int
init(id:Int)
{
self.id=id
}
}
func convertArray(array:[T],target:U)->[U]
{
var newArray=[U]()
对于数组中的元素
{
guard let newElement=元素为?U else
{
打印(“向下播放失败!”)
返回[]
}
追加(新元素)
}
返回新数组
}
让动物:[动物]=[猫(id:1)、猫(id:2)、猫(id:3)]
印刷品(动物)
打印(动物。动态类型)
//错误:无法将类型“[Animal]”的值转换为指定的类型“[Cat]”
//让猫[猫]=动物
//错误:seg故障
//让猫[猫]=动物当宠物![猫]
let cats:[Cat]=convertArray(动物,猫(id:0))
印刷品(猫)
打印(CAT.dynamicType)
map
进行转换:
let cats: [Cat] = animals.map { $0 as! Cat }
func convertArray<T, U>(array: [T]) -> [U] {
var newArray = [U]()
for element in array {
guard let newElement = element as? U else {
print("downcast failed!")
return []
}
newArray.append(newElement)
}
return newArray
}
从Swift 4.1开始,使用
compactMap
将是首选方法,假设您不希望该方法在阵列中有任何其他动物(例如狗)时完全失败(并实际崩溃)
let animals: [Animal] = [Cat(id:1),Dog(id:2),Cat(id:3)]
let cats: [Cat] = animals.compactMap { $0 as? Cat }
由于compactMap
将清除任何nil值,因此最终将得到如下数组:
[Cat(1), Cat(3)]
作为奖励,您还可以通过使用此选项而不是
for
循环来获得一些性能改进。非常感谢,如果对我有效,我将尝试删除U并接受此选项。我曾想过地图,但在实践中,我会扔如果沮丧fails@Philip就掷骰子而言,你可以在地图中做同样的事情。操作员as带有感叹号的代码>也会在不成功的施法中抛出。哦,我没想到map会接受一个抛出的闭包。是的,让我来决定!抛出可能会起作用,但我希望有一个自定义消息与之一起使用for
循环不是性能问题。问题在于没有事先分配足够的容量。
[Cat(1), Cat(3)]