Ich bin mir nicht sicher, welche von beiden Konstanten besser definieren können. Eine Struktur oder eine Aufzählung. Eine Struktur wird jedes Mal kopiert, wenn ich sie benutze oder nicht? Wenn ich an eine Struktur mit static let
Konstanten denke , macht es meiner Meinung nach keinen Sinn, dass sie ständig kopiert wird. Aber wenn es nicht kopiert wird, spielt es keine Rolle, was ich nehme?
Welche Vorteile bringt die Wahl einer Struktur oder Aufzählung?
Francisco sagt, benutze Struct's.
Ray Wenderlich sagt, benutze Enums. Aber mir fehlt die Rechtfertigung.
Antworten:
Sowohl Strukturen als auch Aufzählungen funktionieren. Als Beispiel beides
struct PhysicalConstants { static let speedOfLight = 299_792_458 // ... }
und
enum PhysicalConstants { static let speedOfLight = 299_792_458 // ... }
arbeiten und definieren Sie eine statische Eigenschaft
PhysicalConstants.speedOfLight
.Betreff: Eine Struktur wird jedes Mal kopiert, wenn ich sie benutze oder nicht?
Beide
struct
undenum
sind Werttypen, die auch für Aufzählungen gelten. Aber das ist irrelevant , weil man hier keinen Wert an alle erstellen muß: Statische Eigenschaften (auch als Typ selbst Objekte) sind Eigenschaften des Typs, nicht von einer Instanz dieses Typs.Betreff: Welche Vorteile hat die Wahl einer Struktur oder Aufzählung?
Wie im verlinkten Artikel erwähnt :
Also für eine Struktur,
let foo = PhysicalConstants()
Erstellt einen (nutzlosen) Wert vom Typ
PhysicalConstants
, aber für eine Aufzählung ohne Groß- und Kleinschreibung kann er nicht kompiliert werden:let foo = PhysicalConstants() // error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers
quelle
private init() {}
dasStruct
Beispiel ergänzen , hat es auch den "Vorteil", dass es nicht versehentlich im laufenden Betrieb instanziiert werden kann. (Natürlich könnte dieser "Vorteil" von einigen Entwicklern umgangen werden, indem ein Initialisierer in eine Erweiterung desStruct
: aufgenommen wird. Wenn wir jedoch aus irgendeinem Grund lieberStruct
einen "reinen Namespace" als einen verwenden möchtenenum
, dann den Ein privater Initialisierer könnte ein guter Schutz sein, um ihn nicht als Instanz zu verwenden.struct Constants static let speedOfLight = 300
vs zuenum Constants enum Light : Int case speed = 300
vergleichen. Können Sie diese auch in Ihrer Antwort vergleichen? Oder gibt es eine andere Antwort auf diesen Vergleich?Hier eine kurze Antwort: Müssen Ihre Konstanten eindeutig sein? Verwenden Sie dann eine Aufzählung, die dies erzwingt.
Möchten Sie mehrere verschiedene Konstanten verwenden, um denselben Wert zu enthalten (häufig aus Gründen der Übersichtlichkeit hilfreich)? Verwenden Sie dann eine Struktur, die dies ermöglicht.
quelle
StaticVars.pi.rawValue
Ein Unterschied zwischen den beiden besteht darin, dass Strukturen instanziiert werden können, wo dies bei Aufzählungen nicht möglich ist. In den meisten Szenarien, in denen Sie nur Konstanten verwenden müssen, ist es wahrscheinlich am besten, Aufzählungen zu verwenden, um Verwirrung zu vermeiden.
Zum Beispiel:
struct Constants { static let someValue = "someValue" } let _ = Constants()
Der obige Code wäre weiterhin gültig.
Wenn wir eine Aufzählung verwenden:
enum Constants { static let someValue = "someValue" } let _ = Constants() // error
Der obige Code ist ungültig und vermeidet daher Verwirrung.
quelle
Verwenden von Xcode 7.3.1 und Swift 2.2
Obwohl ich Martin R zustimme und der Ray Wenderlich-Styleguide deutlich macht, dass Aufzählungen in fast allen Anwendungsfällen besser sind, da es sich um einen reinen Namespace handelt, gibt es einen Ort, an dem
struct
Trümpfe verwendet werdenenums
.Anweisungen wechseln
Beginnen wir mit der Strukturversion:
struct StaticVars { static let someString = "someString" } switch "someString" { case StaticVars.someString: print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") }
Mit einer Struktur wird diese übereinstimmen und ausgedruckt
Matched StaticVars.someString
.Betrachten wir nun die Hüllkurven-Enum-Version (indem Sie nur das Schlüsselwort
struct
in ändernenum
):enum StaticVars { static let someString = "someString" } switch "someString" { case StaticVars.someString: print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") }
Sie werden feststellen, dass in der switch-Anweisung in der
case StaticVars.someString:
Zeile ein Fehler bei der Kompilierung angezeigt wird. Der Fehler istEnum case 'someString' not found in type 'String'
.Es gibt eine Pseudo-Problemumgehung, indem die statische Eigenschaft in einen Abschluss konvertiert wird, der stattdessen den Typ zurückgibt.
Sie würden es also folgendermaßen ändern:
enum StaticVars { static let someString = { return "someString" } } switch "someString" { case StaticVars.someString(): print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") }
Beachten Sie die Notwendigkeit von Klammern in der case-Anweisung, da es sich jetzt um eine Funktion handelt.
Der Nachteil ist, dass es jetzt, da wir es zu einer Funktion gemacht haben, jedes Mal ausgeführt wird, wenn es aufgerufen wird. Wenn es also nur ein einfacher primitiver Typ wie
String
oder istInt
, ist das nicht so schlimm. Es ist im Wesentlichen eine berechnete Eigenschaft. Wenn es sich um eine Konstante handelt, die berechnet werden muss und Sie sie nur einmal berechnen möchten, sollten Sie sie in eine andere Eigenschaft berechnen und den bereits berechneten Wert im Abschluss zurückgeben.Sie können den Standardinitialisierer auch mit einem privaten überschreiben, und dann erhalten Sie die gleiche Art von Fehler beim Kompilieren von Fehlern wie bei der Aufzählung ohne Gehäuse.
struct StaticVars { static let someString = "someString" private init() {} }
Damit möchten Sie jedoch die Deklaration der Struktur in eine eigene Datei einfügen. Wenn Sie sie in derselben Datei wie beispielsweise einer View Controller-Klasse deklarieren, kann die Datei dieser Klasse dennoch versehentlich eine nutzlose Datei instanziieren Instanz von
StaticVars
, aber außerhalb der Datei der Klasse würde es wie beabsichtigt funktionieren. Aber es ist dein Anruf.quelle
Im Combine- Framework hat Apple Enums für Namespaces bevorzugt.
quelle