2016-06-07 3 views
0

Hier ist ein einfaches Spielplatz Beispiel:Umgebung lassen Argumente in Swift

class Foobar { 
    var name = "" 

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

    func modifyName(modification:String) { 
     self.name += modification 
    } 
} 

let list = [Foobar(name:"I"), Foobar(name:"Me"), Foobar(name:"Myself")] 

for each in list { 
    each.modifyName(" rules") 
} 

Eine Klasse mit name Variable und eine einzige Funktion, die diese Variable ändern können. Machen Sie eine Liste von ihnen, benutzen Sie jetzt einen for in, um die modifizierende Funktion auszuüben.

ABER.

class Foobar { 
    var name = "" 

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

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

extension Modifiable { 
    mutating func modifyName(modification:String) { 
     self.name += modification 
    } 
} 

extension Foobar:Modifiable { } 

Dann wird die for in werden nicht mehr funktionieren, weil die Modifiable Erweiterung mit Anmerkungen versehen notwendig, um die modifyName als mutating: Wenn ich die modifyName Variable in eine Protokollerweiterung Refactoring. Der ausgegebene Fehler ist error: cannot use mutating member on immutable value: 'each' is a 'let' constant. Es gibt eine einfache Abhilfe, aber es fühlt sich an wie ich etwas zu missbrauchen:

for each in list { 
    var each = each 
    each.modifyName(" rules") 
} 

ich das gleiche Problem mit Funktionen gehabt haben, die ein Argument haben, das mit Anmerkungen versehen getaggt wurde. Früher konnten Sie diese Parameter mit var in der arg-Liste markieren, aber das ist in den neuesten Versionen von swift veraltet. Dieselbe Ein-Zeilen-Problemumgehung funktioniert dort. Gibt es einen besseren idiomatischen Weg, dies zu tun? Was ursprünglich damit anfing, war das einfache Extrahieren eines gemeinsamen Verhaltens in Protokollerweiterungen anstelle eines Vererbungsbaums. Es fühlt sich an, als würde ich eine Strafe für diese Wahl bezahlen.

Antwort

4

Nein, Ihre Ein-Zeilen-Problemumgehung funktioniert nicht unbedingt. Ihr Protokoll erfordert nicht, dass konforme Typen Referenztypen (Klassen) sind. Wenn eine Struktur an Ihr Protokoll angepasst wurde und sich im Array befand, würde var each = each eine Kopie ergeben und die Änderung der Kopie würde den Wert im Array nicht ändern.

Sie könnten verlangen, dass Ihre Objekte Klassen sein, protocol Modifiable: class, in diesem Fall glaube ich, mutating wird nicht mehr erlaubt sein (oder zumindest wird Ihr Code ordnungsgemäß funktionieren).

Aber vorausgesetzt, Sie mutating behalten möchten, können Sie dies tun, um die Elemente in Position zu ändern:

for i in list.indices { 
    list[i].modifyName() 
} 

Natürlich wird Ihr Array auch var sein müssen, weil sie mit value semantics auch eine Struktur ist.

+0

Ich wusste nicht über den Modifikator 'class' für Protokolldeklarationen. Das hilft Tonnen, danke! –

Verwandte Themen