2016-06-12 60 views
2

說我有一個動物數組,並且我想將它投射到一組貓。在這裏,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) 

回答

0
  1. 我失去了一個更簡單的方法來做到這一點?

可以使用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 
    } 
    

    既然你不能明確指定類型的參數,你需要提供編譯器一些信息來推斷的U類型。在這種情況下,所有你需要做的是說你是分配結果的Cat數組:

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

    甜蜜的感謝,我會嘗試刪除U和接受這一點,如果我的作品。我曾想過地圖,但在練習中,如果擊倒失敗,我會拋出 – Philip

    +0

    @Philip就拋出演員而言,你可以在'map'中做同樣的事情。帶有感嘆號的運算符'as!'也會導致不成功的投射。 – dasblinkenlight

    +0

    哦,我不知道地圖可能會引發一個閉包。是的,把它留給!投擲可以工作,但我想有一個自定義的消息與它一起去 – Philip