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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow