Aujourd’hui nous allons parler des types imbriqués (nested types en anglais). Les types imbriqués sont simplement des types que l’on définit à l’intérieurs d’autres types afin de contextualiser leur portés et leurs définissions via les contrôles d’accès (private
, internal
ou public
). Cela permet notamment de mieux organiser le code et de faciliter la lecture. En Swift pour écrire un type imbriqué à l’intérieur d’un autre type, il faut écrire sa définition à l’intérieur des accolades de ce type. Il faut aussi savoir qu’il n’y a pas de limite d’imbrication.
Les types imbriqués en action
L’example que nous allons utiliser dessous définit une structure appelé BlackjackCard
qui représente un jeu de carte. Sa structure contiens deux énumérations imbriquées appelées Suit
et Rank
. Au blackjack l’as a une valeur de 1 ou de 11. Cette particularité est représenté par une structure appelé Values
qui est imbriquée à l’intérieur de l’énumération Rank
:
struct BlackjackCard {
// Enumération imbriquée : Suit
enum Suit: Character {
case Spades = "♠", Hearts = "♡", Diamonds = "♢", Clubs = "♣"
}
// Enumération imbriquée : Rank
enum Rank: Int {
case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King, Ace
// Structure imbriquée : Values
struct Values {
let first: Int, second: Int?
}
var values: Values {
switch self {
case .Ace:
return Values(first: 1, second: 11)
case .Jack, .Queen, .King:
return Values(first: 10, second: nil)
default:
return Values(first: self.rawValue, second: nil)
}
}
}
// Propriétés et méthodes du BlackjackCard
let rank: Rank, suit: Suit
var description: String {
var output = "suit is \(suit.rawValue),"
output += " value is \(rank.values.first)"
if let second = rank.values.second {
output += " or \(second)"
}
return output
}
}
L’énumération Suit
décrit les quatre couleurs de carte avec le Character
comme valeur pour les représenter. L’énumération Rank
lui définit les treize valeurs possible sous forme d’entier. Comme mentionné avant la structure Rank
contient une structure imbriquée appelé Rank
. Cette structure encapsule le fait que des cartes puissent avoir 2 valeurs.
Comme BlackjackCard
est une structure sans initialiser personnalisé il utilise un initialiser implicite basé sur ses membres. Vous pouvez utiliser cet initialiser pour créer une nouvelle constante appelé theAceOfSpades
:
let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// Affiche : "theAceOfSpades: suit is ♠, value is 1 or 11"
Même si Rank
et Suit
sont des types imbriqué à l’intérieur de BlackjackCard
, leur type peut être inféré de leur contexte et donc l’initialiser de cette instance est capable d’utiliser les énumérations uniquement par les noms des cas (.Ace
et .Spades
).
Référence aux types imbriqués
Pour utiliser un type imbriqué en-dehors de son contexte de définition il faut préfixer sont nom avec le nom du type dans lequel il est imbriqué :
let heartsSymbol = BlackjackCard.Suit.Hearts.rawValue
// heartsSymbol est "♡"
Dans l’example du dessus les appels pour arriver jusqu’au Hearts sont ordonner dans le sens naturel de l’imbrication des types.
Ce cours est basé sur la documentation officielle de Swift fournit par Apple.