ProgrammationDéveloppeur iOS intermédiaire

Comment fonctionnent les fonctions d'opérateur (surcharge d'opérateurs en tant que fonctions) en Swift ? Quelles sont les limites de la surcharge, et peut-on créer ses propres opérateurs ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Les fonctions d'opérateur en Swift sont une possibilité de réaliser ou de redéfinir les opérateurs standards (+, -, *, ==, <, etc.), ainsi que de créer ses propres opérateurs (par exemple, %% ou <|>). Pour cela, le mot-clé operator est utilisé dans la déclaration de la fonction. En général, les opérateurs sont surchargés pour travailler avec ses propres types afin de rendre leur utilisation syntaxiquement pratique et intuitive.

Exemple de surcharge de l'addition pour la structure Vector2D :

struct Vector2D { var x: Double var y: Double } func + (lhs: Vector2D, rhs: Vector2D) -> Vector2D { return Vector2D(x: lhs.x + rhs.x, y: lhs.y + rhs.y) } let v1 = Vector2D(x: 1, y: 2) let v2 = Vector2D(x: 3, y: 4) let sum = v1 + v2 // Vector2D(x: 4, y: 6)

Limites :

  • Les opérateurs ne peuvent être surchargés que pour des types propres ou des combinaisons de types standards et propres.
  • On ne peut créer ses propres opérateurs qu'à partir de symboles autorisés en Swift pour les opérateurs (+*-/&|^%~!=<>.?).
  • Il ne faut pas abuser de la création de nouveaux opérateurs au risque de réduire la lisibilité du code.

Question piège.

Peut-on surcharger un opérateur pour les types standards, par exemple, pour changer le sens de l'opérateur + pour Int ?

Réponse : Non, en Swift, il n'est pas possible de redéfinir le comportement global des opérateurs pour les types standards, seulement de les étendre pour ses propres types ou des combinaisons spécifiques. Par exemple :

// Erreur : la surcharge pour Int ne changera pas la sémantique existante+ func + (lhs: Int, rhs: Int) -> Int { return lhs - rhs // Ne fonctionnera pas : conflit avec le comportement existant }

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet.


Histoire

Dans un projet, un nouvel opérateur ** (exposant) a été créé, qui incluait par inadvertance une priorité incorrecte, entraînant des calculs erronés pour des expressions telles que 2 + 3 ** 2. Résultat : résultats incorrects, bug difficile à déboguer.


Histoire

Dans un module avec une API interne, on a surchargé == pour un type propre, mais on n'a pas implémenté le hachage (Hashable), ce qui a conduit à un fonctionnement incorrect des collections Set et Dictionary, où les instances étaient considérées comme différentes en raison de l'égalité logique.


Histoire

Lors de la création d'un nouvel opérateur, les utilisateurs ont oublié de documenter son sens. Un nouveau développeur a mal compris la sémantique de l'opérateur et l'a appliqué à des données inadéquates, ce qui a entraîné des erreurs logiques difficiles à détecter dans la logique métier.