2015-06-08 71 views
8

考慮一個協議的數組和實現它的一類之間進行轉換:夫特:的「協議」陣列和實施

protocol MyProtocol { 
    var x: Int { get } 
} 

class MyClass : MyProtocol { 
    var x: Int = 5 
} 

我有[MyClass]類型的數組和我希望將其分配給一個變量類型爲[MyProtocol]。然而,這會導致嘗試在遊樂場時,一個錯誤(的XCode 6.3,雨燕1.2):

var classArr: [MyClass] = [MyClass(), MyClass()] 

var protocolArrA: [MyProtocol] = classArr // Causes error: EXC_BAD_INSTRUCTION 
var protocolArrB: [MyProtocol] = classArr as [MyProtocol] // Causes error: EXC_BAD_INSTRUCTION 
var protocolArrC: [MyProtocol] = [MyProtocol](classArr) // Causes error: Cannot find an initializer for type [MyProtocol[ that accepts an argument list of type [MyClass] 

是什麼力量讓斯威夫特這項任務的正確方法?

P.S.有趣的是,當使用基類而不是協議時,protocolArrAprotocolArrB的表達式無誤地工作。

這也是有趣的是指定的[MyClass的]一個新創建的實例也是行之有效:

var protocolArrD: [MyProtocol] = [MyClass]() // A-OK! 
+1

託管重現您的問題。它看起來很像一個bug: - /通過classArr.map {$ 0 as MyProtocol}進行手動轉換可能是一種解決方法。 –

回答

10

您可以使用map將每個元素轉換爲所需的類型:

protocol MyProtocol { 
    var x: Int { get } 
} 

class MyClass : MyProtocol { 
    var x: Int = 5 
} 

var classArr: [MyClass] = [MyClass(), MyClass()] 

var protocolArrA:[MyProtocol] = classArr.map{$0 as MyProtocol} 
var andBack:[MyClass] = protocolArrA.map{$0 as! MyClass} 

注意,雨燕能夠推斷以上所有數組類型的,所以這可以被更簡潔地寫爲:

var classArr = [MyClass(), MyClass()] 

var protocolArrA = classArr.map{$0 as MyProtocol} 
var andBack = protocolArrA.map{$0 as! MyClass} 
1

如果使用@objc

var classArr: [MyClass] = [MyClass(), MyClass()]  
var protocolArrA: [MyProtocol] = classArr 
var protocolArrB: [MyProtocol] = classArr as [MyProtocol] 
試試這個

@objc protocol MyProtocol { 
    var x: Int { get } 
} 

class MyClass : MyProtocol { 
    @objc var x: Int = 5 
} 

兩項工程

+0

有意使用classArr類型爲[MyClass]。我不想將它重新定義爲'[MyProtocol]'。實際的代碼要複雜得多,而且我只提取導致問題的部分(這不是依賴於上下文的恕我直言)。 –

+0

我更新了我的答案 – Leo