L'héritage en Swift est l'un des principes de base de la programmation orientée objet, hérité des langages de POO traditionnels tels que Objective-C et C++. Cependant, Swift limite et simplifie considérablement ce mécanisme, en mettant l'accent sur la sécurité des types et la prévisibilité du code.
Dans les premiers langages de POO, tels que C++ et Objective-C, l'héritage était utilisé pour permettre la réutilisation du code et la création d'hiérarchies de classes. Swift a délibérément restreint ce mécanisme pour éviter les problèmes d'héritage multiple et les hiérarchies compliquées.
Les implémentations classiques de l'héritage sont soumises à plusieurs problèmes : ajout implicite de fonctionnalité via des classes parentales, difficulté à maintenir et à tester le code, ainsi que le diamond problem (problème du losange) en cas d'héritage multiple. En Swift, ces problèmes sont partiellement résolus grâce à l'interdiction de l'héritage multiple des classes.
En Swift, seul l'héritage simple des classes est pris en charge. Cela signifie qu'une classe ne peut hériter que d'une seule classe parentale. Pour composer des comportements, il est recommandé d'utiliser des protocoles et leurs extensions.
Exemple d'héritage simple :
class Animal { func speak() { print("Un son") } } class Dog: Animal { override func speak() { print("Ouaf !") } } let animal: Animal = Dog() animal.speak() // "Ouaf !"
Points clés :
superPeut-on redéfinir une propriété déclarée comme let dans une sous-classe en Swift ?
Non. Les propriétés déclarées avec let ne peuvent pas être redéfinies, ce sont des constantes. Pour pouvoir override, utilisez une propriété var avec le modificateur override.
Les structures ou énumérations héritent-elles d'un comportement en Swift ?
Non, seules les classes peuvent hériter les unes des autres. Les structures (struct) et les énumérations (enum) ne supportent pas l'héritage, mais peuvent implémenter des protocoles.
Peut-on créer une classe qui ne peut pas être héritée ?
Oui, utilisez le modificateur final avant la déclaration de la classe. Exemple :
final class Cat { func meow() { print("Miaou !") } } // class Siamese: Cat {} // Erreur de compilation
Un développeur a créé une hiérarchie de classes profonde pour les animaux : Animal -> Mammifère -> Carnivore -> Chien -> Bulldog. Chaque classe ajoute de nouvelles propriétés ou méthodes.
Avantages : La logique est répartie par entités.
Inconvénients : Difficile de gérer le changement de comportement de l'hiérarchie. L'ajout d'un nouveau type d'animal nécessite de modifier plusieurs classes de base, augmentant le risque d'erreurs.
Pour faire la différence entre les animaux, on utilise des protocoles (par exemple, Sitter, Chasseur). Chaque classe implémente les protocoles nécessaires, au lieu de les hériter d'une hiérarchie multi-niveau.
Avantages : La composition des comportements est plus flexible, il est facile d'ajouter de nouveaux types d'animaux sans modifier le code source.
Inconvénients : Nécessite une meilleure compréhension de la programmation orientée protocole, plus difficile au départ.