2015-04-19 16 views
5

Klasse A stellt einen Zeichenfolgenwert bereit. Klasse B hat zwei Mitglieder des A-Typs in sich selbst und stellt eine berechnete Eigenschaft "v" bereit, um eine von ihnen auszuwählen.Swift: Konnte Wert zu einer Eigenschaft des Protokolls nicht zuweisen?

class A { 
    var value: String 

    init(value: String) { 
     self.value = value 
    } 
} 

class B { 
    var v1: A? 
    var v2: A = A(value: "2") 

    private var v: A { 
     return v1 ?? v2 
    } 

    var value: String { 
     get { 
      return v.value 
     } 
     set { 
      v.value = newValue 
     } 
    } 
} 

Dieser Code ist einfach und es funktioniert. Da sowohl die A- und B ein Element "Wert" haben, mache ich es ein Protokoll wie folgt aus:

protocol ValueProvider { 
    var value: String {get set} 
} 

class A: ValueProvider { 
    var value: String 

    init(value: String) { 
     self.value = value 
    } 
} 

class B: ValueProvider { 
    var v1: ValueProvider? 
    var v2: ValueProvider = A(value: "2") 

    private var v: ValueProvider { 
     return v1 ?? v2 
    } 

    var value: String { 
     get { 
      return v.value 
     } 
     set { 
      v.value = newValue // Error: Cannot assign to the result of the expression 
     } 
    } 
} 

Wenn ich den folgenden Code ändern

v.value = newValue 

zu

var v = self.v 
v.value = newValue 

Es funktioniert wieder!

Ist dies ein Fehler von Swift oder etwas Besonderes für die Eigenschaft von Protokollen?

Antwort

10

Sie haben das Protokoll als class Protokoll zu definieren:

protocol ValueProvider : class { 
    var value: String {get set} 
} 

Dann

var value: String { 
    get { return v.value } 
    set { v.value = newValue } 
} 

kompiliert und funktioniert wie erwartet (dh ordnet den neuen Wert zu dem Objekt durch v1 wenn v1 != nil verwiesen und auf das Objekt , das ansonsten durch v2 referenziert wird).

v ist eine schreibgeschützte berechnete Eigenschaft des Typs ValueProvider. das Protokolls als Klasse-Protokoll der Compiler Durch die Definition kennt dass v eine Art Referenz und kann daher seine v.value Eigenschaft geändert werden, selbst wenn die Referenz selbst eine Konstante ist.

Ihr ursprüngliches Codebeispiel funktioniert, weil dort die v Eigenschaft den Typ A hat, der ein Referenztyp ist.

Und Ihre Abhilfe

set { 
    var tmp = v1 ?? v2 
    tmp.value = newValue 
} 

funktioniert, weil (read-write) Eigenschaften von Variablen können in jeden Fall (Werttyp oder Referenztyp) eingestellt werden.

+0

Schöne Antwort und danke. –

Verwandte Themen