In der Einführung in die Swift WWDC-Sitzung wird eine schreibgeschützte Eigenschaft description
demonstriert:
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description)
Gibt es irgendwelche Auswirkungen, wenn Sie stattdessen den oben genannten Ansatz anstelle einer Methode wählen:
class Vehicle {
var numberOfWheels = 0
func description() -> String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description())
Es scheint mir, dass die offensichtlichsten Gründe, warum Sie sich für eine schreibgeschützte berechnete Eigenschaft entscheiden würden, folgende sind:
- Semantik - In diesem Beispiel ist es sinnvoll
description
, eine Eigenschaft der Klasse zu sein und keine Aktion, die sie ausführt. - Kürze / Klarheit - verhindert, dass beim Abrufen des Werts leere Klammern verwendet werden müssen.
Das obige Beispiel ist natürlich zu einfach, aber gibt es andere gute Gründe, sich für eines zu entscheiden? Gibt es beispielsweise einige Merkmale von Funktionen oder Eigenschaften, die Sie bei Ihrer Entscheidung für eine Verwendung unterstützen?
NB Auf den ersten Blick scheint dies eine häufig gestellte OOP-Frage zu sein, aber ich bin gespannt auf alle Swift-spezifischen Funktionen, die als Best Practice bei der Verwendung dieser Sprache dienen.
quelle
get {}
? Das wusste ich nicht, danke!Antworten:
Es scheint mir, dass es hauptsächlich eine Frage des Stils ist: Ich bevorzuge es stark, Eigenschaften dafür zu verwenden: Eigenschaften; Dies bedeutet einfache Werte, die Sie erhalten und / oder festlegen können. Ich benutze Funktionen (oder Methoden), wenn die eigentliche Arbeit erledigt wird. Möglicherweise muss etwas von der Festplatte oder aus einer Datenbank berechnet oder gelesen werden: In diesem Fall verwende ich eine Funktion, auch wenn nur ein einfacher Wert zurückgegeben wird. Auf diese Weise kann ich leicht erkennen, ob ein Anruf billig (Eigenschaften) oder möglicherweise teuer (Funktionen) ist.
Wir werden wahrscheinlich mehr Klarheit bekommen, wenn Apple einige Swift-Codierungskonventionen veröffentlicht.
quelle
Nun, Sie können die Ratschläge von Kotlin unter https://kotlinlang.org/docs/reference/coding-conventions.html#functions-vs-properties anwenden .
quelle
Während eine Frage der berechneten Eigenschaften gegenüber Methoden im Allgemeinen schwierig und subjektiv ist, gibt es derzeit ein wichtiges Argument im Fall von Swift, um Methoden gegenüber Eigenschaften vorzuziehen. Sie können Methoden in Swift als reine Funktionen verwenden, was für Eigenschaften nicht gilt (ab Swift 2.0 Beta). Dies macht Methoden viel leistungsfähiger und nützlicher, da sie an der funktionellen Zusammensetzung teilnehmen können.
quelle
Da die Laufzeit gleich ist, gilt diese Frage auch für Objective-C. Ich würde sagen, mit Eigenschaften, die Sie bekommen
readwrite
didSet
für Änderungsbenachrichtigungen zu verwendenWas Swift betrifft, ist das einzige Beispiel, das ich habe, dass Sie es
@lazy
für eine Eigenschaft verwenden können.quelle
Es gibt einen Unterschied: Wenn Sie eine Eigenschaft verwenden, können Sie sie eventuell überschreiben und in einer Unterklasse lesen / schreiben.
quelle
willSet
unddidSet
zur Basisklasse hinzufügt , ohne etwas über zukünftige abgeleitete Klassen zu wissen, kann Änderungen in der überschriebenen Eigenschaft erkennen. Aber so etwas kann man mit Funktionen nicht machen, denke ich.Im schreibgeschützten Fall sollte eine berechnete Eigenschaft nicht als semantisch äquivalent zu einer Methode betrachtet werden, selbst wenn sie sich identisch verhält, da durch das Löschen der
func
Deklaration die Unterscheidung zwischen Mengen, die den Status einer Instanz umfassen, und Mengen, die lediglich Funktionen der sind, verwischt wird Zustand. Sie sparen die Eingabe()
an der Anrufstelle, riskieren jedoch, die Klarheit Ihres Codes zu verlieren.Betrachten Sie als triviales Beispiel den folgenden Vektortyp:
Durch die Deklaration der Länge als Methode wird deutlich, dass es sich um eine Funktion des Zustands handelt, die nur von
x
und abhängty
.Auf der anderen Seite, wenn Sie
length
als berechnete Eigenschaft ausdrücken würdenWenn Sie dann in Ihrer IDE auf einer Instanz von einen Punkt-Tab-Vervollständigen ausführen
VectorWithLengthAsProperty
, sieht es so aus, als obx
,y
,length
Eigenschaften auf gleiche Augenhöhe waren, die konzeptionell falsch ist.quelle
Es gibt Situationen, in denen Sie berechnete Eigenschaften normalen Funktionen vorziehen würden. Zum Beispiel: Rückgabe des vollständigen Namens einer Person. Sie kennen bereits den Vor- und Nachnamen. Also wirklich die
fullName
Eigenschaft ist eine Eigenschaft, keine Funktion. In diesem Fall handelt es sich um eine berechnete Eigenschaft (da Sie den vollständigen Namen nicht festlegen können, können Sie ihn einfach mit dem Vor- und Nachnamen extrahieren).quelle
Aus Sicht der Leistung scheint es keinen Unterschied zu geben. Wie Sie im Benchmark-Ergebnis sehen können.
Kern
main.swift
Code-Auszug:Ausgabe:
prop: 0.0380070209503174 func: 0.0350250005722046 prop: 0.371925950050354 func: 0.363085985183716 prop: 3.4023300409317 func: 3.38373708724976 prop: 33.5842199325562 func: 34.8433820009232 Program ended with exit code: 0
In der Tabelle:
quelle
Date()
ist nicht für Benchmarks geeignet, da die Computeruhr verwendet wird, die vom Betriebssystem automatisch aktualisiert wird.mach_absolute_time
würde zuverlässigere Ergebnisse erhalten.Semantisch gesehen sollten berechnete Eigenschaften eng mit dem inneren Zustand des Objekts gekoppelt sein. Wenn sich andere Eigenschaften nicht ändern, sollte die Abfrage der berechneten Eigenschaft zu unterschiedlichen Zeiten dieselbe Ausgabe ergeben (vergleichbar über == oder ===) - ähnlich eine reine Funktion für dieses Objekt aufzurufen.
Methoden hingegen werden mit der Annahme ausgeliefert, dass wir möglicherweise nicht immer die gleichen Ergebnisse erzielen, da Swift keine Möglichkeit hat, Funktionen als rein zu kennzeichnen. Außerdem werden Methoden in OOP als Aktionen betrachtet, was bedeutet, dass ihre Ausführung zu Nebenwirkungen führen kann. Wenn die Methode keine Nebenwirkungen hat, kann sie sicher in eine berechnete Eigenschaft konvertiert werden.
Beachten Sie, dass beide obigen Aussagen rein semantisch sind, da es durchaus vorkommen kann, dass berechnete Eigenschaften Nebenwirkungen haben, die wir nicht erwarten, und Methoden rein sind.
quelle
Historisch gesehen ist die Beschreibung eine Eigenschaft von NSObject und viele würden erwarten, dass sie in Swift dieselbe bleibt. Das Hinzufügen von Parens nach dem Hinzufügen führt nur zu Verwirrung.
EDIT: Nach heftigem Downvoting muss ich etwas klarstellen - wenn über die Punktsyntax darauf zugegriffen wird, kann es als Eigenschaft betrachtet werden. Es ist egal, was sich unter der Haube befindet. Mit der Punktsyntax können Sie nicht auf übliche Methoden zugreifen.
Außerdem erforderte das Aufrufen dieser Eigenschaft keine zusätzlichen Parens, wie im Fall von Swift, was zu Verwirrung führen kann.
quelle
description
ist eine erforderliche Methode für dasNSObject
Protokoll und wird daher in Ziel-C mit zurückgegeben[myObject description]
. Wie auch immer, die Eigenschaftdescription
war nur ein erfundenes Beispiel - ich suche nach einer allgemeineren Antwort, die für jede benutzerdefinierte Eigenschaft / Funktion gilt.