Polymorfisme is een fundamenteel principe van objectgeoriënteerd programmeren, dat objecten met verschillende structuren in staat stelt om dezelfde interface te implementeren en dus uitwisselbaar te zijn. In Python, met dynamische typering, is polymorfisme zeer flexibel opgezet.
In talen met strikte statische typering (Java, C++) vereist de ondersteuning van polymorfisme de verklaring van interfaces of abstracte klassen. In Python — dankzij duck typing — is polymorfisme niet gebonden aan een erfgoedhiërarchie of zelfs aan een interface. Het belangrijkste is dat het object de benodigde methoden/attributen ondersteunt.
Enerzijds maakt dit de taal flexibel en gebruiksvriendelijk. Aan de andere kant verhoogt het de kans op fouten tijdens runtime vanwege typfouten of ontbrekende benodigde methoden, die pas blijken tijdens de uitvoering van de code.
In Python maken we onderscheid tussen:
class Animal: def speak(self): raise NotImplementedError class Dog(Animal): def speak(self): return 'Woef!' class Cat(Animal): def speak(self): return 'Miauw!' def animal_voice(animal): print(animal.speak()) animal_voice(Dog()) # Woef! animal_voice(Cat()) # Miauw!
class Duck: def quack(self): return 'Quak!' def make_quack(animal): print(animal.quack()) make_quack(Duck()) # Quak!
Belangrijke kenmerken:
Is overerving de enige manier om polymorfisme in Python te waarborgen?
Nee. Dankzij duck typing kan elke functie een object met de benodigde methoden accepteren, ongeacht zijn klasse of hiërarchie.
Kan overeenstemming van de handtekening alleen op basis van de naam van de methode, en niet op zijn essentie, als polymorfisme worden beschouwd?
Nee. Als een object de benodigde methode ondersteunt, maar de semantiek verschilt van wat verwacht werd — kunnen er bugs ontstaan. Polymorfisme is alleen succesvol wanneer zowel de interface als de betekenis overeenkomen.
Biedt een abstracte klasse bescherming tegen fouten door verkeerd geïmplementeerde interfaces in subklassen?
Slechts gedeeltelijk. Als de afstammeling de abstracte methode niet implementeert — wordt er een TypeError gegenereerd bij de poging om een instantie te maken. Maar als hij deze implementeert met een strijdige logica — zijn fouten mogelijk.
In de loggingbibliotheek wordt een externe klasse geïntroduceerd, die een log()-methode heeft, maar die retourneert een gegevensobject in plaats van een logboekinvoer. Fouten komen alleen aan het licht tijdens exploitatie.
Voordelen:
Nadelen:
Klassen zijn voorzien van tests, de interface wordt geformaliseerd via een abstracte basis klasse en @abstractmethod, en de semantiek van de methoden is vastgelegd in de documentatie.
Voordelen:
Nadelen: