2016-12-10 3 views
1

den folgenden Code vor:Protokolltyp nicht instanziiert werden kann

protocol Color { 
    var color: UIColor { get } 
} 

struct Ball : Color { 
    var color: UIColor 
} 

let ball = Ball(color: .white) 
print(ball) 

Dies funktioniert, und die Ergebnisse in:

Ball(color: UIExtendedGrayColorSpace 1 1) 

Nun, ich möchte eine Funktion im Protokoll machen, dass angesichts einer Palette von Farben, gibt ein Array von Gegenständen (Kugeln, oder jede andere Art, den Color entspricht) mit dieser Farbe:

extension Color { 
    func multipleColors(colors: [UIColor]) -> [Color] { 
     var coloredItems = [Color]() 
     for item in colors { 
     // What do I put here ??? 
     } 

     return coloredItems 
    } 
} 

und dann:

let coloredBalls = ball.multipleColors(colors: [.red, .green, .blue]) 

Ich kann nicht herausfinden, was in den Klammern zu setzen. Zum Beispiel (kein Wortspiel), wenn ich versuche:

coloredItems.append(Color(color: item)) 

der Fehler ist:

'Color' cannot be constructed because it has no accessible initializers 

ich dann eine Init-Methode zu dem Protokoll hinzugefügt, und der Fehler folgendermaßen geändert:

protocol type 'Color' cannot be instantiated 

Wie behebe ich das?

+1

Sie versuchen, eine Instanz eines Protokolls 'Farbe zu erstellen (Farbe: Artikel)', was nicht möglich ist. – shallowThought

+0

Also irgendwelche Ideen, wie man das ändert? – Koen

+0

Es ist nicht klar, was genau Sie erwarten, dass die Ausgabe Ihrer 'multipleColors'-Funktion ist. Was ist das eigentliche Problem, das du hier zu lösen versuchst? – Hamish

Antwort

1

Sie versuchen, eine Instanz eines Protokolls Color(color: item) zu erstellen, was nicht möglich ist.

Hier finden Sie eine mögliche generische Lösung. Ich konnte bisher keine nicht statische (nette) Lösung finden.

protocol Color { 
    var color: UIColor {get set} 
    init(color: UIColor) 
} 

struct Ball : Color { 
    var color: UIColor 
} 

extension Color { 
    static func item<T:Color>(_ item: T, inColors colors: [UIColor]) -> [T] { 
     var coloredItems = [T]() 
     for color in colors { 
      let newColoredItem = T.init(color: color) 
      coloredItems.append(newColoredItem) 
     } 

     return coloredItems 
    } 
} 

let ball = Ball(color: .white) 
let coloredBalls = type(of:ball).item(ball, inColors: [.red, .green, .blue]) 

print(coloredBalls) 

Drucke:

[Ball(color: UIExtendedSRGBColorSpace 1 0 0 1), Ball(color: UIExtendedSRGBColorSpace 0 1 0 1), Ball(color: UIExtendedSRGBColorSpace 0 0 1 1)] 
+0

Ich mag diese Lösung und werde sie akzeptieren, da sie die Frage beantwortet. "Ball" hat jedoch auch mehr Eigenschaften wie "size" (die ich aus Gründen der Klarheit weggelassen habe), und diese müssen auch auf "colouredItems" propagiert werden. – Koen

+0

Ich betrachtete dies als ein eher theoretisches Beispiel. Benutze in der Praxis eine Klasse. Sie möchten wissen, ob 'alicesBall === bobsBall'. Außerdem würde ich 'Color' löschen. Erstelle 'class ColouredItem {var Farbe: UIColor func multipleColors() ...'. Und Unterklasse es. – shallowThought

+1

Sie können auch eine 'copy' Funktion einfügen und sie verwenden:' T.copy() 'anstelle von' T.init() '. – shallowThought

Verwandte Themen