Recherche…


Remarques

Tout comme les classes et les classes, les énumérations sont des types de valeurs et sont copiées au lieu d'être référencées lorsqu'elles sont transmises.

Pour plus d'informations sur les énumérations, voir Le langage de programmation Swift .

Énumérations de base

Une énumération fournit un ensemble de valeurs connexes:

enum Direction {
    case up
    case down
    case left
    case right
}

enum Direction { case up, down, left, right }

Les valeurs Enum peuvent être utilisées par leur nom complet, mais vous pouvez omettre le nom du type lorsqu'il peut être déduit:

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

La méthode la plus fondamentale pour comparer / extraire des valeurs enum consiste à utiliser une instruction 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
}

Les Hashable simples sont automatiquement Hashable , Equatable et ont des conversions de chaînes:

if dir == .down { ... }

let dirs: Set<Direction> = [.right, .left]

print(Direction.up)  // prints "up"
debugPrint(Direction.up)  // prints "Direction.up"

Enums avec des valeurs associées

Les cas d'énumération peuvent contenir une ou plusieurs charges utiles ( valeurs associées ):

enum Action {
    case jump
    case kick
    case move(distance: Float)  // The "move" case has an associated distance
}

Le payload doit être fourni lors de l’instanciation de la valeur enum:

performAction(.jump)
performAction(.kick)
performAction(.move(distance: 3.3))
performAction(.move(distance: 0.5))

L'instruction switch peut extraire la valeur associée:

switch action {
case .jump:
    ...
case .kick:
    ...
case .move(let distance):  // or case let .move(distance):
    print("Moving: \(distance)") 
}

Une extraction de cas unique peut être effectuée en utilisant if case :

if case .move(let distance) = action {
    print("Moving: \(distance)") 
}

La syntaxe du guard case peut être utilisée pour l'extraction ultérieure:

guard case .move(let distance) = action else {
    print("Action is not move")
    return
}

Les énumérations associées à des valeurs ne sont pas Equatable par défaut. L'implémentation de l'opérateur == doit être effectuée manuellement:

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
}

Charges indirectes

Normalement, les énumérations ne peuvent pas être récursives (car elles nécessiteraient un stockage infini):

enum Tree<T> {
    case leaf(T)
    case branch(Tree<T>, Tree<T>)  // error: recursive enum 'Tree<T>' is not marked 'indirect'
}

Le mot-clé indirect fait que l'enum stocke ses données utiles avec une couche d'indirection plutôt que de les stocker en ligne. Vous pouvez utiliser ce mot clé sur un seul cas:

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 fonctionne également sur l'ensemble de l'énumération, rendant chaque cas indirect lorsque nécessaire:

indirect enum Tree<T> {
    case leaf(T)
    case branch(Tree<T>, Tree<T>)
}

Valeurs brutes et hachages

Les énumérations sans données utiles peuvent avoir des valeurs brutes de tout type littéral:

enum Rotation: Int {
    case up = 0
    case left = 90
    case upsideDown = 180
    case right = 270
}

Les énumérations sans type spécifique n'exposent pas la propriété rawValue

enum Rotation {
    case up
    case right
    case down
    case left
}

let foo = Rotation.up
foo.rawValue //error

Les valeurs brutes entières sont supposées commencer à 0 et augmenter de manière monotone:

enum MetasyntacticVariable: Int {
    case foo  // rawValue is automatically 0
    case bar  // rawValue is automatically 1
    case baz = 7
    case quux  // rawValue is automatically 8
}

Les valeurs brutes peuvent être synthétisées automatiquement:

enum MarsMoon: String {
    case phobos  // rawValue is automatically "phobos"
    case deimos  // rawValue is automatically "deimos"
}

Un enum à valeur brute est automatiquement conforme à RawRepresentable . Vous pouvez obtenir la valeur brute correspondante avec .rawValue :

func rotate(rotation: Rotation) {
    let degrees = rotation.rawValue
    ...
}

Vous pouvez également créer une énumération à partir d' une valeur brute à l'aide d' 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)")
}

Si vous souhaitez obtenir la valeur de hachage d'une enum spécifique, vous pouvez accéder à sa hashValue. La valeur de hachage renverra l'index de l'enum à partir de zéro.

let quux = MetasyntacticVariable(rawValue: 8)// rawValue is 8
quux?.hashValue //hashValue is 3

Initialiseurs

Enums peuvent avoir des méthodes d'initialisation personnalisées qui peuvent être plus utiles que l' init?(rawValue:) par défaut init?(rawValue:) . Enums peut également stocker des valeurs. Cela peut être utile pour stocker les valeurs avec lesquelles ils ont été initialisés et pour récupérer cette valeur ultérieurement.

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
        }    
    }
}

En utilisant cet initialiseur, nous pouvons faire ceci:

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

Les énumérations partagent de nombreuses fonctionnalités avec les classes et les structures

Enums Swift sont beaucoup plus puissants que certains de leurs homologues dans d'autres langues, telles que C. Ils partagent de nombreuses fonctionnalités avec des classes et des structures , telles que la définition d' initialiseurs , de propriétés calculées , de méthodes d'instance , de conformités de protocole et d' extensions .

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

Enumérations imbriquées

Vous pouvez imbriquer les énumérations les unes dans les autres, cela vous permet de structurer les énumérations hiérarchiques pour qu'elles soient plus organisées et claires.

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
    }
}

Et vous pouvez l'utiliser comme ça:

let instrment1 = Orchestra.Strings.viola
let instrment2 = Orchestra.Keyboards.piano


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow