Polymorphisme — principe fondamental de la programmation orientée objet, qui permet aux objets de structures différentes de réaliser la même interface, et donc de fonctionner de manière interchangeable. En Python, avec typage dynamique, le polymorphisme est mis en place de manière très flexible.
Dans les langages avec typage statique strict (Java, C++), la prise en charge du polymorphisme nécessite la déclaration d'interfaces ou de classes abstraites. En Python — grâce au duck typing — le polymorphisme n'est pas lié à la hiérarchie d'héritage ni même à l'interface. L'essentiel est que l'objet supporte les méthodes/attributs requis.
D'une part, cela rend le langage flexible et pratique. D'autre part — cela augmente la probabilité d'erreurs à l'exécution en raison de fautes de frappe ou de l'absence de la méthode requise, qui ne se manifesteront qu'à l'exécution du code.
En Python, on distingue :
class Animal: def speak(self): raise NotImplementedError class Dog(Animal): def speak(self): return 'Woof!' class Cat(Animal): def speak(self): return 'Meow!' def animal_voice(animal): print(animal.speak()) animal_voice(Dog()) # Woof! animal_voice(Cat()) # Meow!
class Duck: def quack(self): return 'Quack!' def make_quack(animal): print(animal.quack()) make_quack(Duck()) # Quack!
Caractéristiques clés :
L'héritage est-il le seul moyen d'assurer le polymorphisme en Python ?
Non. Grâce au duck typing, toute fonction peut accepter un objet avec les méthodes requises indépendamment de sa classe ou de sa hiérarchie.
Peut-on considérer comme polymorphisme le simple fait que la signature correspond au nom de la méthode, et non à son contenu ?
Non. Si un objet supporte la méthode requise mais que sa sémantique diffère de celle attendue, des bugs peuvent apparaître. Le polymorphisme réussit seulement lorsque l'interface et le sens coïncident.
Un classe abstraite protège-t-elle contre les erreurs d'une mauvaise implémentation d'interface dans les classes dérivées ?
Seulement partiellement. Si un héritier n'implémente pas la méthode abstraite, un TypeError se produira lors de la tentative de création d'une instance. Mais s'il l'implémente avec des erreurs logiques, des erreurs peuvent survenir.
Une bibliothèque de journalisationintègre une classe tierce, qui possède une méthode log(), mais elle renvoie un objet de données au lieu d'écrire dans le journal. Les erreurs se manifestent uniquement lors de l'exploitation.
Avantages :
Inconvénients :
Les classes sont accompagnées de tests, l'interface est formalisée par le biais d'une classe de base abstraite et @abstractmethod, la documentation décrit la sémantique des méthodes.
Avantages :
Inconvénients :