2016-04-28 10 views
0

Kann mir bitte jemand sagen, warum Swift den Setter einer Eigenschaft aufrufen muss, wenn es nur für den Zugriff auf ein Objekt (ein Protokoll) verwendet wird, um eine seiner Eigenschaften festzulegen? Dieses erste Beispiel zeigt den Fehler ich, wenn ich das indirekte Objekt als einstellbares nicht erklären kann:Swift-Protokoll einstellbare Eigenschaft durch eine schreibgeschützte Eigenschaft

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

class AnImplementation: AProtocol { 
    var name = "" 
} 

class AParent { 
    var test = AnImplementation() 
} 

class AChild { 
    var parent: AParent! 

    var test: AProtocol { 
     get { return parent.test } 
     // Note: Not settable 
    } 
} 

var parent = AParent() 
var child = AChild() 
child.parent = parent 

child.test.name = "Hello world!" // Error: Cannot assign to property : 'test' is a get-only property 
print(child.test.name) 

Wenn ich ihm einen Setter geben, es kompiliert und funktioniert, aber es ruft den Setzer:

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

class AnImplementation: AProtocol { 
    var name = "" 
} 

class AParent { 
    var test = AnImplementation() 
} 

class AChild { 
    var parent: AParent! 

    var test: AProtocol { 
     get { return parent.test } 
     set(newTest) { print("Shouldn't be here!") } 
    } 
} 

var parent = AParent() 
var child = AChild() 
child.parent = parent 

child.test.name = "Hello world!" 
print(child.test.name) 

Ausgang ist:

Shouldn't be here! 
Hello world! 

ich bin nicht sicher, was ich hier nicht zu verstehen. Ich nehme an, ich kann es einfach einen leeren Setter geben, aber ich würde gerne den Grund dafür verstehen.

Alle Informationen werden sehr geschätzt!

Antwort

2

Ihre Protokollerklärung zu dieser Änderung:

protocol AProtocol:class { 
    var name: String { get set } 
} 

Andernfalls wird standardmäßig als Werttyp genommen wird. Das Ändern der Eigenschaft eines Werttyps ersetzt die Werttypinstanz (wie vom Setter-Beobachter angezeigt). Und Sie können das nicht tun, wenn die Referenz eine let Referenz ist.

+0

Auf Werttyp Setter, siehe zum Beispiel meine Antwort hier: http://StackOverflow.com/A/33901138/341994 – matt

2

Das liegt wahrscheinlich daran, dass der Compiler nicht weiß, ob AChild.test eine Klasse oder ein Werttyp ist. Mit Klassen gibt es kein Problem, aber mit Werttypen, die name zuweisen, würde auch eine Zuweisung zu test (Wertkopieverhalten) erstellt. Markierung APProtocol als class Protokoll wird das Problem beheben.

zu erweitern, wenn der Compiler nicht sicher ist, ob test ein Wert ist oder ein Klasse-Typ, wird die folgenden Umschreibungs von child.test.name = "Hello world!" verwenden:

var tmp = child.test 
tmp.test = "Hello world!" 
child.test = tmp 

, weil das für beiden Klassen und Werttypen funktioniert.

Verwandte Themen