Duck Typing
Kurz: Duck Typing bedeutet: Ein Objekt wird danach beurteilt, was es kann, nicht, welcher Klasse es angehört. „Wenn es läuft wie eine Ente und quakt wie eine Ente, dann ist es eine Ente.“
Genauer: In dynamischen Sprachen wie Python, Ruby und JavaScript genügt es, dass ein Objekt die benötigten Methoden besitzt; eine gemeinsame Basisklasse oder Schnittstelle ist nicht nötig. Passt etwas nicht, fällt das erst zur Laufzeit auf. Go und TypeScript kennen eine statisch geprüfte Variante, die strukturelle Typisierung.
Im Detail
class Ente:
def quaken(self): return "Quak"
class Roboter:
def quaken(self): return "Beep-Quak"
def lass_quaken(wesen):
print(wesen.quaken()) # braucht nur eine Methode quaken()
lass_quaken(Ente()) # Quak
lass_quaken(Roboter()) # Beep-Quak
lass_quaken(42) # AttributeError: 'int' object has no attribute 'quaken'type Quaker interface{ Quaken() string } // Go: Typen erfüllen Schnittstellen implizit
type Ente struct{}
func (Ente) Quaken() string { return "Quak" }interface Quaker { quaken(): string }
const ente = { quaken: () => "Quak" }; // passt strukturell, ohne "implements"
const q: Quaker = ente;Vor- und Nachteile
| Vorteile | Nachteile |
|---|---|
| sehr flexibel, wenig Code | Fehler erst zur Laufzeit |
| leicht zu testen (Attrappen sind einfach Objekte) | Erwartungen stehen nur in der Dokumentation |
| fördert lose Kopplung | IDE-Hilfen sind schwächer |
Mit Typannotationen (Python Protocol, TypeScript) bekommt man die Flexibilität mit Prüfung. Eng verwandt ist die Polymorphie; Gegenstück ist die nominale Typisierung in Java und C#, wo Klassen ihre Schnittstellen ausdrücklich deklarieren (siehe Typsysteme).
Siehe auch: Polymorphie, Schnittstelle, Typsysteme, Typinferenz