Swift Language
Aufzählungen
Suche…
Bemerkungen
Wie bei Strukturen und im Gegensatz zu Klassen handelt es sich bei Enums um Werttypen, die beim Weitergeben nicht referenziert, sondern kopiert werden.
Weitere Informationen zu Enums finden Sie unter Die Swift-Programmiersprache .
Grundaufzählungen
Eine Aufzählung enthält eine Reihe verwandter Werte:
enum Direction {
case up
case down
case left
case right
}
enum Direction { case up, down, left, right }
Aufzählungswerte können mit ihrem vollständig qualifizierten Namen verwendet werden. Sie können jedoch den Typnamen weglassen, wenn er abgeleitet werden kann:
let dir = Direction.up
let dir: Direction = Direction.up
let dir: Direction = .up
// func move(dir: Direction)...
move(Direction.up)
move(.up)
obj.dir = Direction.up
obj.dir = .up
Die grundlegendste Methode zum Vergleichen / Extrahieren von Aufzählungswerten besteht in einer switch
Anweisung:
switch dir {
case .up:
// handle the up case
case .down:
// handle the down case
case .left:
// handle the left case
case .right:
// handle the right case
}
Einfache Aufzählungen sind automatisch Hashable
, Equatable
und haben String-Konvertierungen:
if dir == .down { ... }
let dirs: Set<Direction> = [.right, .left]
print(Direction.up) // prints "up"
debugPrint(Direction.up) // prints "Direction.up"
Aufzählungen mit zugehörigen Werten
Aufzählungsfälle können eine oder mehrere Nutzdaten ( zugehörige Werte ) enthalten:
enum Action {
case jump
case kick
case move(distance: Float) // The "move" case has an associated distance
}
Die Nutzlast muss angegeben werden, wenn der Aufzählungswert instanziiert wird:
performAction(.jump)
performAction(.kick)
performAction(.move(distance: 3.3))
performAction(.move(distance: 0.5))
Die switch
Anweisung kann den zugehörigen Wert extrahieren:
switch action {
case .jump:
...
case .kick:
...
case .move(let distance): // or case let .move(distance):
print("Moving: \(distance)")
}
Eine Einzelfall-Extraktion kann mit if case
:
if case .move(let distance) = action {
print("Moving: \(distance)")
}
Die guard case
Syntax kann zur späteren Extraktion verwendet werden:
guard case .move(let distance) = action else {
print("Action is not move")
return
}
Aufzählungen mit zugehörigen Werten sind standardmäßig nicht Equatable
. Die Implementierung des Operators ==
muss manuell erfolgen:
extension Action: Equatable { }
func ==(lhs: Action, rhs: Action) -> Bool {
switch lhs {
case .jump: if case .jump = rhs { return true }
case .kick: if case .kick = rhs { return true }
case .move(let lhsDistance): if case .move (let rhsDistance) = rhs { return lhsDistance == rhsDistance }
}
return false
}
Indirekte Nutzlasten
Normalerweise können Aufzählungen nicht rekursiv sein (da sie unendlich viel Speicherplatz benötigen):
enum Tree<T> {
case leaf(T)
case branch(Tree<T>, Tree<T>) // error: recursive enum 'Tree<T>' is not marked 'indirect'
}
Mit dem indirect
Schlüsselwort speichert das Enum seine Nutzdaten mit einer Ebene von Indirection, anstatt es inline zu speichern. Sie können dieses Schlüsselwort in einem einzelnen Fall verwenden:
enum Tree<T> {
case leaf(T)
indirect case branch(Tree<T>, Tree<T>)
}
let tree = Tree.branch(.leaf(1), .branch(.leaf(2), .leaf(3)))
indirect
funktioniert auch auf der gesamten Aufzählung und macht jeden Fall indirekt, wenn nötig:
indirect enum Tree<T> {
case leaf(T)
case branch(Tree<T>, Tree<T>)
}
Roh- und Hashwerte
Aufzählungen ohne Payloads können Rohwerte eines beliebigen Literaltyps haben:
enum Rotation: Int {
case up = 0
case left = 90
case upsideDown = 180
case right = 270
}
Aufzählungen ohne bestimmten Typ machen die rawValue-Eigenschaft nicht verfügbar
enum Rotation {
case up
case right
case down
case left
}
let foo = Rotation.up
foo.rawValue //error
Es wird angenommen, dass ganzzahlige Rohwerte bei 0 beginnen und monoton ansteigen:
enum MetasyntacticVariable: Int {
case foo // rawValue is automatically 0
case bar // rawValue is automatically 1
case baz = 7
case quux // rawValue is automatically 8
}
String-Rohwerte können automatisch synthetisiert werden:
enum MarsMoon: String {
case phobos // rawValue is automatically "phobos"
case deimos // rawValue is automatically "deimos"
}
Ein Rohwert entspricht automatisch RawRepresentable . Mit .rawValue
können Sie den entsprechenden Rohwert eines Aufzählungswerts .rawValue
:
func rotate(rotation: Rotation) {
let degrees = rotation.rawValue
...
}
Sie können mit init?(rawValue:)
auch eine Aufzählung aus einem Rohwert init?(rawValue:)
:
let rotation = Rotation(rawValue: 0) // returns Rotation.Up
let otherRotation = Rotation(rawValue: 45) // returns nil (there is no Rotation with rawValue 45)
if let moon = MarsMoon(rawValue: str) {
print("Mars has a moon named \(str)")
} else {
print("Mars doesn't have a moon named \(str)")
}
Wenn Sie den Hashwert einer bestimmten Enumeration abrufen möchten, können Sie auf dessen Hashwert zugreifen. Der Hashwert gibt den Index der Enumeration ab Null zurück.
let quux = MetasyntacticVariable(rawValue: 8)// rawValue is 8
quux?.hashValue //hashValue is 3
Initialisierer
Enums können benutzerdefinierte Init-Methoden haben, die nützlicher sein können als die Standardinitialisierung init?(rawValue:)
. Aufzählungen können auch Werte speichern. Dies kann nützlich sein, um die Werte zu speichern, mit denen sie initialisiert wurden, und um diesen Wert später abzurufen.
enum CompassDirection {
case north(Int)
case south(Int)
case east(Int)
case west(Int)
init?(degrees: Int) {
switch degrees {
case 0...45:
self = .north(degrees)
case 46...135:
self = .east(degrees)
case 136...225:
self = .south(degrees)
case 226...315:
self = .west(degrees)
case 316...360:
self = .north(degrees)
default:
return nil
}
}
var value: Int = {
switch self {
case north(let degrees):
return degrees
case south(let degrees):
return degrees
case east(let degrees):
return degrees
case west(let degrees):
return degrees
}
}
}
Mit diesem Initialisierer können wir Folgendes tun:
var direction = CompassDirection(degrees: 0) // Returns CompassDirection.north
direction = CompassDirection(degrees: 90) // Returns CompassDirection.east
print(direction.value) //prints 90
direction = CompassDirection(degrees: 500) // Returns nil
Aufzählungen teilen viele Funktionen mit Klassen und Strukturen
Enums in Swift sind viel leistungsfähiger als einige ihrer Kollegen in anderen Sprachen, wie z. B. C. Sie teilen viele Features mit Klassen und Strukturen , z. B. Definieren von Initialisierern , berechneten Eigenschaften , Instanzmethoden , Protokollkonformitäten und Erweiterungen .
protocol ChangesDirection {
mutating func changeDirection()
}
enum Direction {
// enumeration cases
case up, down, left, right
// initialise the enum instance with a case
// that's in the opposite direction to another
init(oppositeTo otherDirection: Direction) {
self = otherDirection.opposite
}
// computed property that returns the opposite direction
var opposite: Direction {
switch self {
case .up:
return .down
case .down:
return .up
case .left:
return .right
case .right:
return .left
}
}
}
// extension to Direction that adds conformance to the ChangesDirection protocol
extension Direction: ChangesDirection {
mutating func changeDirection() {
self = .left
}
}
var dir = Direction(oppositeTo: .down) // Direction.up
dir.changeDirection() // Direction.left
let opposite = dir.opposite // Direction.right
Verschachtelte Aufzählungen
Sie können Enumerationen ineinander verschachteln. Dadurch können Sie hierarchische Enumerationen strukturierter und klarer strukturieren.
enum Orchestra {
enum Strings {
case violin
case viola
case cello
case doubleBasse
}
enum Keyboards {
case piano
case celesta
case harp
}
enum Woodwinds {
case flute
case oboe
case clarinet
case bassoon
case contrabassoon
}
}
Und du kannst es so benutzen:
let instrment1 = Orchestra.Strings.viola
let instrment2 = Orchestra.Keyboards.piano