Ich versuche mit der neuen Apple Swift-Sprache etwas herauszufinden. Nehmen wir an, ich habe in Objective-C so etwas wie das Folgende gemacht. Ich habe readonly
Eigenschaften und sie können nicht individuell geändert werden. Mit einer bestimmten Methode werden die Eigenschaften jedoch auf logische Weise geändert.
Ich nehme das folgende Beispiel, eine sehr einfache Uhr. Ich würde dies in Objective-C schreiben.
@interface Clock : NSObject
@property (readonly) NSUInteger hours;
@property (readonly) NSUInteger minutes;
@property (readonly) NSUInteger seconds;
- (void)incrementSeconds;
@end
@implementation Clock
- (void)incrementSeconds {
_seconds++;
if (_seconds == 60) {
_seconds = 0;
_minutes++;
if (_minutes == 60) {
_minutes = 0;
_hours++;
}
}
}
@end
Für einen bestimmten Zweck können wir die Sekunden, Minuten und Stunden nicht direkt berühren, und es ist nur zulässig, Sekunden für Sekunden mithilfe einer Methode zu erhöhen. Nur diese Methode kann die Werte mithilfe des Tricks der Instanzvariablen ändern.
Da es in Swift keine solchen Dinge gibt, versuche ich, ein Äquivalent zu finden. Wenn ich das mache:
class Clock : NSObject {
var hours: UInt = 0
var minutes: UInt = 0
var seconds: UInt = 0
func incrementSeconds() {
self.seconds++
if self.seconds == 60 {
self.seconds = 0
self.minutes++
if self.minutes == 60 {
self.minutes = 0
self.hours++
}
}
}
}
Das würde funktionieren, aber jeder könnte die Eigenschaften direkt ändern.
Vielleicht hatte ich bereits ein schlechtes Design in Objective-C und deshalb macht das potenzielle neue Swift-Äquivalent keinen Sinn. Wenn nicht und wenn jemand eine Antwort hat, wäre ich sehr dankbar;)
Vielleicht sind die von Apple versprochenen zukünftigen Zugriffskontrollmechanismen die Antwort?
Vielen Dank!
quelle
Antworten:
Stellen Sie der Eigenschaftsdeklaration einfach Folgendes vor
private(set)
:private
Hält es lokal für eine Quelldatei, währendinternal
es lokal für das Modul / Projekt bleibt.private(set)
Erstellt eineread-only
Eigenschaft, währendprivate
beideset
undget
privat festgelegt werden.quelle
Es gibt zwei grundlegende Möglichkeiten, um das zu tun, was Sie wollen. Der erste Weg besteht darin, ein privates Eigentum und ein öffentliches berechnetes Eigentum zu haben, das dieses Eigentum zurückgibt:
Dies kann jedoch auf eine andere, kürzere Weise erreicht werden, wie im Abschnitt "Zugriffskontrolle" des Buches "The Swift Programming Language" angegeben :
Als Randnotiz MÜSSEN Sie einen öffentlichen Initialisierer angeben, wenn Sie einen öffentlichen Typ deklarieren. Auch wenn Sie für alle Eigenschaften Standardwerte angeben,
init()
muss diese explizit öffentlich definiert werden:Dies wird auch im selben Abschnitt des Buches erläutert, wenn es um Standardinitialisierer geht.
quelle
Da es keine Zugriffskontrollen gibt (was bedeutet, dass Sie keinen Zugriffsvertrag abschließen können, der je nach Anrufer unterschiedlich ist), würde ich Folgendes vorerst tun:
Dies fügt lediglich eine Ebene der Indirektion hinzu, um den direkten Zugriff auf den Zähler zu ermöglichen. Eine andere Klasse kann eine Uhr erstellen und dann direkt auf ihren Zähler zugreifen. Die Idee - dh der Vertrag, den wir abschließen möchten - ist jedoch, dass eine andere Klasse nur die Eigenschaften und Methoden der obersten Ebene der Uhr verwenden sollte. Wir können diesen Vertrag nicht durchsetzen , aber tatsächlich war es so gut wie unmöglich, ihn auch in Objective-C durchzusetzen.
quelle
Tatsächlich ist die Zugriffskontrolle (die in Swift noch nicht vorhanden ist) nicht so erzwungen, wie Sie vielleicht in Ziel C denken. Benutzer können Ihre schreibgeschützten Variablen direkt ändern, wenn sie dies wirklich möchten. Sie tun es einfach nicht mit der öffentlichen Schnittstelle der Klasse.
Sie können in Swift etwas Ähnliches tun (Ausschneiden und Einfügen Ihres Codes sowie einige Änderungen, die ich nicht getestet habe):
Dies entspricht dem, was Sie in Ziel C haben, außer dass die tatsächlich gespeicherten Eigenschaften in der öffentlichen Oberfläche sichtbar sind.
In Swift können Sie auch etwas Interessanteres tun, was Sie auch in Objective C tun können, aber in Swift ist es wahrscheinlich schöner (im Browser bearbeitet, ich habe es nicht getestet):
quelle