Methodenüberschreibung erneut betrachtet
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 33 von 91.
Du hast im Kapitel zur Vererbung bereits etwas über das Überschreiben von Methoden gelernt. Sehen wir uns nun an, wie es mit dem Polymorphismus zusammenhängt – einem der leistungsfähigsten Konzepte in der objektorientierten Programmierung.
Polymorphismus bedeutet „viele Formen“. Wenn du eine Methode in einer Kindklasse überschreibst, gibst du dieser Methode eine andere Form, behältst aber denselben Namen bei. Der Zauber geschieht, wenn du mit Objekten über ihren übergeordneten Typ arbeitest:
<?php
class Animal {
public function speak() {
return "Some sound";
}
}
class Dog extends Animal {
public function speak() {
return "Woof!";
}
}
class Cat extends Animal {
public function speak() {
return "Meow!";
}
}
function makeAnimalSpeak(Animal $animal) {
return $animal->speak();
}
echo makeAnimalSpeak(new Dog()) . "\n";
echo makeAnimalSpeak(new Cat());
Ausgabe:
Woof!
Meow!Die Funktion makeAnimalSpeak() akzeptiert jedes Animal. Sie weiß nicht und kümmert sich nicht darum, ob sie ein Dog oder eine Cat erhält. PHP ruft automatisch die richtige überschriebene Methode auf, basierend auf dem tatsächlichen Objekttyp zur Laufzeit.
Das ist Polymorphismus in Aktion.
Mit diesem Ansatz kannst du flexiblen Code schreiben, der mit einer Familie verwandter Objekte funktioniert, ohne deren spezifische Typen zu kennen. Du kannst später neue Tierklassen hinzufügen, und die Funktion funktioniert automatisch mit ihnen.
Wichtiger Punkt: Das Überschreiben von Methoden ermöglicht Polymorphie, indem verschiedene Klassen auf denselben Methodenaufruf unterschiedlich reagieren können. Welche Reaktion erfolgt, wird zur Laufzeit durch den tatsächlichen Objekttyp bestimmt.
Aufgabe
EinfachLass uns ein Musikinstrument-System entwickeln, das Polymorphismus durch Methodenüberschreibung demonstriert. Du erstellst eine Basisklasse Instrument und zwei Kindklassen, die jeweils ihren eigenen einzigartigen Klang erzeugen, und verwendest anschließend eine einzige Funktion, um jedes Instrument polymorph zu spielen.
Du organisierst deinen Code über vier Dateien:
Instrument.php: Erstelle eine KlasseInstrumentmit einer geschützten Eigenschaft$name, die über den Konstruktor festgelegt wird. Füge eine Methodeplay()hinzu, die"[name] makes a sound"zurückgibt. Dies dient als Basisverhalten, das die Kindklassen überschreiben werden.Guitar.php: Erstelle eine KlasseGuitar, dieInstrumenterweitert. Binde die übergeordnete Datei ein. Der Konstruktor akzeptiert den Namen und übergibt ihn an den Konstruktor der übergeordneten Klasse. Überschreibe die Methodeplay(), sodass sie"[name] strums a chord"zurückgibt.Drum.php: Erstelle eine KlasseDrum, dieInstrumenterweitert. Binde die übergeordnete Datei ein. Der Konstruktor akzeptiert den Namen und übergibt ihn an den Konstruktor der übergeordneten Klasse. Überschreibe die Methodeplay(), sodass sie"[name] beats a rhythm"zurückgibt.main.php: Binde sowohl die Dateien Guitar als auch Drum ein. Erstelle eine Funktion namensperformWith, die einen typisierten ParameterInstrumentakzeptiert und das Ergebnis des Aufrufs vonplay()darauf zurückgibt. Diese Funktion demonstriert Polymorphismus. Sie funktioniert dank des Typhinweises der übergeordneten Klasse mit jedem Instrumenttyp.
Du erhältst zwei Eingaben: einen Namen für die Gitarre und einen Namen für die Trommel. Erstelle mit diesen Namen ein Guitar- und ein Drum-Objekt. Übergib beide nacheinander an deine Funktion performWith() und gib die Ergebnisse aus: zuerst die Gitarre, dann die Trommel, jeweils in einer eigenen Zeile.
Beachte, wie performWith() jedes Instrument akzeptiert, PHP jedoch automatisch die richtige überschriebene play()-Methode auf Grundlage des tatsächlichen Objekttyps zur Laufzeit aufruft. Das ist Polymorphismus in Aktion!
Probier es selbst
<?php
// Die Instrument-Dateien einbinden
require_once 'Guitar.php';
require_once 'Drum.php';
// Eingabe lesen
$guitarName = trim(fgets(STDIN));
$drumName = trim(fgets(STDIN));
// TODO: Erstelle eine Funktion namens performWith, die:
// - Einen Instrument-Parameter akzeptiert (verwende Type-Hint: Instrument $instrument)
// - Das Ergebnis des Aufrufs von play() auf dem Instrument zurückgibt
// TODO: Erstelle eine Guitar mit $guitarName und eine Drum mit $drumName
// TODO: Übergebe jedes an performWith() und gib die Ergebnisse aus (zuerst Gitarre, dann Trommel)
?>Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler