Swift Language
Enums
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