2014-12-02 11 views
36

Ich hämmere meinen Kopf gegen die Wand mit dem folgenden Code in Swift. Ich habe ein einfaches Protokoll definiert:Kann nicht Eigenschaft im Protokoll zuweisen - Swift Compiler Fehler

protocol Nameable { 
    var name : String { get set } 
} 

und umgesetzt, dass mit:

class NameableImpl : Nameable { 
    var name : String = "" 
} 

und dann habe ich die folgende Methode in einer anderen Datei (fragen Sie mich nicht warum):

func nameNameable(nameable: Nameable, name: String) { 
    nameable.name = name 
} 

das Problem ist, dass der Compiler für die Eigenschaftszuweisung in diesem Verfahren die folgenden Fehler gibt:

kann auf 'Name' in 'benennbaren'

Ich kann nicht sehen, nicht abtreten, was ich falsch mache ... Der folgende Code kompiliert fein:

var nameable : Nameable = NameableImpl() 
nameable.name = "John" 

Ich bin Sicher, es ist etwas Einfaches, das ich übersehen habe - was mache ich falsch?

Antwort

30

Es ist, weil, Umbenennbar ein Protokoll ist, Swift nicht weiß, was Art (Geschmack) von Objekt Ihrer Funktion der eingehende Umbenennbar ist. Es könnte eine Klasseninstanz sein, sicher - aber es könnte eine Strukturinstanz sein. Und Du kann nicht auf eine Eigenschaft einer konstanten Struktur, weist wie das folgende Beispiel zeigt:

struct NameableStruct : Nameable { 
    var name : String = "" 
} 
let ns = NameableStruct(name:"one") 
ns.name = "two" // can't assign 

Nun, standardmäßig ein eingehender Funktionsparameter ist eine Konstante - es ist genau so, wie wenn Sie hatte let in Ihrer Funktionserklärung gesagt, bevor Sie nameable sagten.

Die Lösung ist es, diesen Parameter zu machen keine Konstante sein:

func nameNameable(var nameable: Nameable, name: String) { 
        ^^^ 
+0

tl; dr change "lassen myProtocolConformingItem" auf "var myProtocolConformingItem" –

+0

@ Matt Während dieser Vorschlag/Lösung auf jeden Fall funktioniert und wird derzeit sogar vom Compiler vorgeschlagen, halten Sie es für einen Code-Geruch? – damirstuhec

+0

Ich erhalte den Fehler 'Gebrauch von undeclared Art benennbarer' – Jack

76

@ Matts anwer korrekt ist. Eine andere Lösung besteht darin, Nameable als class only protocol zu deklarieren.

protocol Nameable: class { 
//    ^^^^^^^ 
    var name : String { get set } 
} 

Ich denke, diese Lösung ist für diesen Fall besser geeignet. Weil nameNameable nutzlos ist, es sei denn, nameable ist eine Instanz von class.

+0

Meine Wertschätzung für Swift wurde dadurch größer. –

+0

Diese +10000.Ich hatte große Probleme mit der Implementierung eines Protokolls und Erweiterungen, die eine struct -Eigenschaft beinhalteten, und war nicht in der Lage, es ohne alle möglichen Kopfschmerzen zu verändern, aber das Hinzufügen von 'class' löste alles. – Mike

+0

Warum funktioniert das, aber nicht "Protokoll benennbar wo Self: UIView" (vorausgesetzt, Sie wollten nur, dass Sichten dieses Protokoll erben). UIView ist eine Klasse, aber es wird seinen Fehler nicht wirklich beseitigen. – GoldenJoe

0

Hier, ich einige Code geschrieben, die eine Vorstellung auf Verbundenen generischer Typ Usage geben könnte:

protocol NumaricType 
{ 
    typealias elementType 
    func plus(lhs : elementType, _ rhs : elementType) -> elementType 
    func minus(lhs : elementType, _ rhs : elementType) -> elementType 
} 

struct Arthamatic :NumaricType { 

func addMethod(element1 :Int, element2 :Int) -> Int { 
    return plus(element1, element2) 
} 
func minusMethod(ele1 :Int, ele2 :Int) -> Int { 
    return minus(ele1, ele2) 
} 
typealias elementType = Int 

func plus(lhs: elementType, _ rhs: elementType) -> elementType { 
    return lhs + rhs 
} 
func minus(lhs: elementType, _ rhs: elementType) -> elementType { 
    return lhs - rhs 
} 
} 
**Output:** 
let obj = Arthamatic().addMethod(34, element2: 45) // 79 
Verwandte Themen