Swift Language
enums
Zoeken…
Opmerkingen
Net als structs en in tegenstelling tot klassen, zijn enums waardetypes en worden ze gekopieerd in plaats van waarnaar wordt verwezen wanneer ze worden doorgegeven.
Zie De snelle programmeertaal voor meer informatie over enums.
Fundamentele opsommingen
Een opsomming biedt een reeks gerelateerde waarden:
enum Direction {
case up
case down
case left
case right
}
enum Direction { case up, down, left, right }
Enum-waarden kunnen worden gebruikt door hun volledig gekwalificeerde naam, maar u kunt de typenaam weglaten wanneer deze kan worden afgeleid:
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
De meest fundamentele manier om enumwaarden te vergelijken / extraheren is met een switch
:
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
}
Eenvoudige enums zijn automatisch Hashable
, Equatable
en hebben stringconversies:
if dir == .down { ... }
let dirs: Set<Direction> = [.right, .left]
print(Direction.up) // prints "up"
debugPrint(Direction.up) // prints "Direction.up"
Enums met bijbehorende waarden
Aantal gevallen kunnen een of meer payloads ( bijbehorende waarden ) bevatten:
enum Action {
case jump
case kick
case move(distance: Float) // The "move" case has an associated distance
}
De payload moet worden opgegeven bij het instantiëren van de enumwaarde:
performAction(.jump)
performAction(.kick)
performAction(.move(distance: 3.3))
performAction(.move(distance: 0.5))
De switch
kan de bijbehorende waarde extraheren:
switch action {
case .jump:
...
case .kick:
...
case .move(let distance): // or case let .move(distance):
print("Moving: \(distance)")
}
Een enkele case-extractie kan worden gedaan met behulp van if case
:
if case .move(let distance) = action {
print("Moving: \(distance)")
}
De guard case
syntax gebruikt kan worden voor later gebruik extractie:
guard case .move(let distance) = action else {
print("Action is not move")
return
}
Enums met bijbehorende waarden zijn standaard niet Equatable
. Implementatie van de operator ==
moet handmatig worden uitgevoerd:
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
}
Indirecte payloads
Normaal gesproken kunnen enums niet recursief zijn (omdat ze oneindige opslag vereisen):
enum Tree<T> {
case leaf(T)
case branch(Tree<T>, Tree<T>) // error: recursive enum 'Tree<T>' is not marked 'indirect'
}
Het indirect
trefwoord zorgt ervoor dat het opsomming zijn lading met een laag van richting bewaart, in plaats van het inline op te slaan. U kunt dit trefwoord in één geval gebruiken:
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
werkt ook over het geheel, waardoor elk geval indien nodig indirect wordt:
indirect enum Tree<T> {
case leaf(T)
case branch(Tree<T>, Tree<T>)
}
Raw- en Hash-waarden
Enums zonder payloads kunnen onbewerkte waarden van elk letterlijk type hebben:
enum Rotation: Int {
case up = 0
case left = 90
case upsideDown = 180
case right = 270
}
Enums zonder een specifiek type onthullen de eigenschap rawValue niet
enum Rotation {
case up
case right
case down
case left
}
let foo = Rotation.up
foo.rawValue //error
Er wordt aangenomen dat ruwe gehele waarden beginnen bij 0 en monotoon toenemen:
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 raw-waarden kunnen automatisch worden gesynthetiseerd:
enum MarsMoon: String {
case phobos // rawValue is automatically "phobos"
case deimos // rawValue is automatically "deimos"
}
Een ruw gewaardeerde opsomming voldoet automatisch aan RawRepresentable . U kunt de bijbehorende ruwe waarde van een opsommingswaarde krijgen met .rawValue
:
func rotate(rotation: Rotation) {
let degrees = rotation.rawValue
...
}
U kunt ook een opsomming maken van een onbewerkte waarde met 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)")
}
Als je de hash-waarde van een specifieke opsomming wilt krijgen, kun je de hashValue openen. De hash-waarde retourneert de index van de opsomming vanaf nul.
let quux = MetasyntacticVariable(rawValue: 8)// rawValue is 8
quux?.hashValue //hashValue is 3
initialiseerders
Enums kunnen aangepaste init-methoden hebben die nuttiger kunnen zijn dan de standaard init?(rawValue:)
. Enums kunnen ook waarden opslaan. Dit kan handig zijn voor het opslaan van de waarden waarmee ze zijn geïnitialiseerd en om die waarde later op te halen.
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
}
}
}
Met behulp van die initialisatie kunnen we dit doen:
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
Opsommingen delen veel functies met klassen en structuren
Enums in Swift zijn veel krachtiger dan sommige van hun tegenhangers in andere talen, zoals C. Ze delen veel functies met klassen en structuren , zoals het definiëren van initialisators , berekende eigenschappen , instantiemethoden , protocolconformanties en uitbreidingen .
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
Geneste opsommingen
Je kunt opsommingen in elkaar nesten, hierdoor kun je hiërarchische enums beter structureren en overzichtelijker maken.
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
}
}
En je kunt het zo gebruiken:
let instrment1 = Orchestra.Strings.viola
let instrment2 = Orchestra.Keyboards.piano