Contexte de la question :
Le subscript est un mécanisme d'accès aux valeurs à l'intérieur des collections, des structures et d'autres types à l'aide de crochets. Il a été ajouté à Swift par analogie avec d'autres langages (par exemple, l'indexation dans les tableaux Python, l'opérateur [] en C++/Java), afin de rendre le travail avec des collections et des objets similaires plus intuitif.
Problème :
Tous les types ne prennent pas en charge par défaut l'accès par index comme un tableau. Lorsqu'on a une structure ou une classe avec des données, l'accès aux éléments est souvent plus logique à réaliser à travers une syntaxe familière (comme myObject[index]), plutôt qu'à l'aide d'une méthode.
Solution :
Swift permet de créer soi-même des subscripts pour tout type personnalisé. On peut le faire pour la lecture ou l'écriture. Par exemple : une structure qui implémente un subscript pour travailler avec une matrice carrée :
struct Matrix { let size: Int private var grid: [Int] init(size: Int) { self.size = size self.grid = Array(repeating: 0, count: size * size) } subscript(row: Int, column: Int) -> Int { get { precondition(indexIsValid(row, column), "Index out of range") return grid[(row * size) + column] } set { precondition(indexIsValid(row, column), "Index out of range") grid[(row * size) + column] = newValue } } private func indexIsValid(_ row: Int, _ column: Int) -> Bool { return row >= 0 && row < size && column >= 0 && column < size } } var m = Matrix(size: 3) m[1,2] = 7 print(m[1,2]) // 7
Caractéristiques clés :
Les subscripts peuvent-ils être utilisés uniquement pour des collections ?
Non, les subscripts peuvent être implémentés pour n'importe quel type : structure, classe, enum. Le type de données à l'intérieur ne doit pas nécessairement être une collection, l'essentiel est la logique de traitement des requêtes via le subscript.
Peut-on créer plusieurs subscripts avec des signatures différentes dans un même type ?
Oui, il est permis de surcharger les subscripts avec des signatures de paramètres différentes :
struct Example { subscript(index: Int) -> Int { return index } subscript(key: String) -> String { return key.uppercased() } }
Est-il autorisé d'utiliser un subscript comme propriété calculée sans set ?
Oui, le subscript peut être en lecture seule (get-only), toute tentative d'écriture générera une erreur de compilation.
struct ReadOnly { subscript(index: Int) -> Int { index * index } }
Dans une grande structure, un subscript a été réalisé sans vérification de plage, ce qui entraîne un plantage de l'application en cas d'indice incorrect.
Avantages :
Inconvénients :
La matrice a été réalisée avec une précondition sur la plage d'indices. Toute erreur est immédiatement capturée, ne passe pas en production.
Avantages :
Inconvénients :