ProgrammationDéveloppeur iOS

Qu'est-ce que le subscripting en Swift et comment implémenter un subscript personnalisé pour sa propre structure ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

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 :

  • Le subscript peut accepter n'importe quel nombre d'arguments, pas seulement un index.
  • Il est réalisé à l'aide du mot-clé subscript et peut être uniquement en lecture ou en lecture/écriture.
  • Il permet de créer une API conviviale et lisible pour des collections ou des structures personnalisées.

Questions pièges.

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

Erreurs typiques et anti-modèles

  • Absence de vérification des plages d'indices (Index out of range)
  • Violation du principe de “responsabilité unique” — le subscript contient de la logique métier, et pas seulement un accès aux données.
  • Signatures de subscript trop complexes et peu évidentes.

Exemple de la vie réelle

Cas négatif

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 :

  • Prototype rapide
  • Moins de code

Inconvénients :

  • Haute probabilité de runtime-crash
  • Difficultés de débogage à cause d'une erreur peu évidente.

Cas positif

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 :

  • Sécurité dans le traitement des entrées
  • Diagnostic et maintenance faciles

Inconvénients :

  • Un peu plus de code et de vérifications, mais fiabilité accrue.