Swift:将对象阵列转换为子类型的数组

问题描述:

说我有一个动物数组,并且我想将它投射到一组猫。在这里,Animal是Cat采用的协议。我想像let cats: [Cat] = animals as! [Cat],但这段编译故障(顺便说一句,我在Linux Swift 3和Mac Swift 2.2)。我的解决方法是创建一个函数,分别向下转发每个项目并将其添加到新数组(请参见下面的小示例)。它产生了理想的结果,但并不像我想的那么干净。Swift:将对象阵列转换为子类型的数组

我的问题是:

  1. 这是完全愚蠢的,我只是缺少一个更简单的方法来做到这一点?

  2. 如何在下面的函数中传递一个类型作为目标参数,而不是传递一个实例? (例如,我想通过Cat.self,而不是猫(ID:0),但这样做会导致一个错误,说不能Cat.Type转换为预期的参数类型猫)

这里是我到目前为止:

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) 

  1. 我失去了一个更简单的方法来做到这一点?

可以使用map进行转换:

let cats: [Cat] = animals.map { $0 as! Cat } 
  1. 如何能够传递一个类型为目标参数在功能下面,而不是传递一个实例?
开始=>

首先,你需要删除实例参数:

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 
} 

既然你不能明确指定类型的参数,你需要提供编译器一些信息来推断的U类型。在这种情况下,所有你需要做的是说你是分配结果的Cat数组:

let cats: [Cat] = convertArray(animals) 
+0

甜蜜的感谢,我会尝试删除U和接受这一点,如果我的作品。我曾想过地图,但在练习中,如果击倒失败,我会抛出 – Philip

+0

@Philip就抛出演员而言,你可以在'map'中做同样的事情。带有感叹号的运算符'as!'也会导致不成功的投射。 – dasblinkenlight

+0

哦,我不知道地图可能会引发一个闭包。是的,把它留给!投掷可以工作,但我想有一个自定义的消息与它一起去 – Philip