2015-06-08 18 views
8

Rozważmy protokołu i klasy, która implementuje go:Swift: konwersji pomiędzy tablicami „Protokół” i tablice realizacji Klasa

protocol MyProtocol { 
    var x: Int { get } 
} 

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

Mam tablicę typu [MyClass] i życzę, aby przypisać ją do zmiennej typu [MyProtocol]. Jednak to powoduje błąd przy próbie w Playground (XCode 6.3, Swift 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] 

Jaki jest prawidłowy sposób, aby to zadanie w Swift?

P.S. Co ciekawe, przy korzystaniu z klasy bazowej zamiast protokołu, wyrażenia dla protocolArrA i protocolArrB działają bezbłędnie.

Warto również zauważyć, że przypisanie nowo utworzonej instancji [MojaKlasa] również działa dobrze:

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

Udało się odtworzyć problem. Wydaje się bardzo podobny do błędu: -/Ręczny rzut przez 'classArr.map {$ 0 jako MyProtocol}' może być obejściem problemu. –

Odpowiedz

10

Za pomocą mapy można rzutować każdy element na żądany typ:

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} 

Uwaga, Swift jest w stanie wywnioskować wszystkich typów tablicowych powyżej, więc to może być zapisany jako bardziej zwięźle:

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

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

Spróbuj tego

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

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

Obie prace w przypadku korzystania @objc

var classArr: [MyClass] = [MyClass(), MyClass()]  
var protocolArrA: [MyProtocol] = classArr 
var protocolArrB: [MyProtocol] = classArr as [MyProtocol] 
+0

classArr jest celowo typu "[MyClass]". Nie chcę ponownie definiować go jako '[MyProtocol]'. Rzeczywisty kod jest znacznie bardziej złożony, a ja destylowałem tylko fragmenty powodujące problem (co nie jest zależnym od kontekstu IMHO). –

+0

Uaktualniam swoją odpowiedź – Leo

Powiązane problemy