Method Overriding erneut betrachtet
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 33 von 91.
Sie haben bereits im Kapitel über Vererbung etwas über das Überschreiben von Methoden gelernt. Lassen Sie uns nun untersuchen, wie dies mit Polymorphismus zusammenhängt – einem der mächtigsten Konzepte in der objektorientierten Programmierung.
Polymorphismus bedeutet „viele Formen“. Wenn Sie eine Methode in einer untergeordneten Klasse überschreiben, geben Sie dieser Methode eine andere Form, während Sie denselben Namen beibehalten. Der Zauber geschieht, wenn Sie mit Objekten über ihren übergeordneten Typ arbeiten:
<?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 es ist ihr egal, ob sie ein Dog oder eine Cat erhält. PHP ruft automatisch die korrekte überschriebene Methode auf, basierend auf dem tatsächlichen Objekttyp zur Laufzeit.
Das ist Polymorphismus in Aktion.
Dieser Ansatz ermöglicht es Ihnen, flexiblen Code zu schreiben, der mit einer Familie verwandter Objekte arbeitet, ohne deren spezifische Typen zu kennen. Sie können später neue Tierklassen hinzufügen, und die Funktion wird automatisch mit ihnen funktionieren.
Kernpunkt: Das Überschreiben von Methoden ermöglicht Polymorphismus, indem es verschiedenen Klassen erlaubt, unterschiedlich auf denselben Methodenaufruf zu reagieren, was zur Laufzeit durch den tatsächlichen Objekttyp bestimmt wird.
Aufgabe
EinfachLassen Sie uns ein Musikinstrumenten-System bauen, das Polymorphismus durch das Überschreiben von Methoden demonstriert. Sie erstellen eine Basisklasse Instrument und zwei Kindklassen, die jeweils ihren eigenen einzigartigen Klang erzeugen — und verwenden dann eine einzige Funktion, um jedes Instrument polymorph abzuspielen.
Sie werden Ihren Code über vier Dateien organisieren:
Instrument.php— Erstellen Sie eine KlasseInstrumentmit einer geschützten Eigenschaft$name, die über den Konstruktor gesetzt wird. Fügen Sie eine Methodeplay()hinzu, die"[name] makes a sound"zurückgibt. Dies dient als Basisverhalten, das die Kindklassen überschreiben werden.Guitar.php— Erstellen Sie eine KlasseGuitar, dieInstrumenterweitert. Binden Sie die Datei der Elternklasse ein. Der Konstruktor akzeptiert den Namen und übergibt ihn an den Konstruktor der Elternklasse. Überschreiben Sie die Methodeplay(), sodass sie"[name] strums a chord"zurückgibt.Drum.php— Erstellen Sie eine KlasseDrum, dieInstrumenterweitert. Binden Sie die Datei der Elternklasse ein. Der Konstruktor akzeptiert den Namen und übergibt ihn an den Konstruktor der Elternklasse. Überschreiben Sie die Methodeplay(), sodass sie"[name] beats a rhythm"zurückgibt.main.php— Binden Sie sowohl die Guitar- als auch die Drum-Dateien ein. Erstellen Sie eine Funktion namensperformWith, die einen Parameter vom TypInstrument(Type-Hinting) akzeptiert und das Ergebnis des Aufrufs vonplay()darauf zurückgibt. Diese Funktion demonstriert Polymorphismus — sie funktioniert mit jedem Instrumententyp durch den Type-Hint der Elternklasse.
Sie erhalten zwei Eingaben: einen Namen für die Gitarre und einen Namen für die Trommel. Erstellen Sie eine Guitar und eine Drum mit diesen Namen. Übergeben Sie jedes Objekt an Ihre Funktion performWith() und geben Sie die Ergebnisse aus — zuerst die Gitarre, dann die Trommel, jeweils in einer eigenen Zeile.
Beachten Sie, wie performWith() jedes Instrument akzeptiert, PHP jedoch zur Laufzeit automatisch die korrekte überschriebene Methode play() basierend auf dem tatsächlichen Objekttyp aufruft. Das ist Polymorphismus in Aktion!
Spickzettel
Polymorphismus bedeutet „viele Formen“ und ermöglicht es, Objekte verschiedener Klassen über ihren Elterntyp zu behandeln, während ihr spezifisches Verhalten beibehalten wird.
Wenn Sie eine Methode in Kindklassen überschreiben, ruft PHP automatisch die korrekte Version basierend auf dem tatsächlichen Objekttyp zur Laufzeit auf:
<?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()); // Woof!
echo makeAnimalSpeak(new Cat()); // Meow!
Die Funktion makeAnimalSpeak() akzeptiert jeden Animal-Typ über ihren Parameter-Type-Hint. Sie muss die spezifische Klasse nicht kennen – PHP bestimmt zur Laufzeit basierend auf dem tatsächlichen Objekttyp, welche überschriebene Methode aufgerufen werden soll.
Dies ermöglicht flexiblen Code, der mit einer Familie verwandter Objekte arbeitet, ohne deren spezifische Typen zu kennen. Neue Kindklassen können später hinzugefügt werden und funktionieren automatisch mit bestehenden Funktionen.
Probier es selbst
<?php
// Die Instrumentendateien einbinden
require_once 'Guitar.php';
require_once 'Drum.php';
// Eingabe lesen
$guitarName = trim(fgets(STDIN));
$drumName = trim(fgets(STDIN));
// TODO: Erstellen Sie eine Funktion namens performWith, die:
// - Einen Instrument-Parameter akzeptiert (Type Hint verwenden: Instrument $instrument)
// - Das Ergebnis des Aufrufs von play() auf dem Instrument zurückgibt
// TODO: Erstellen Sie eine Guitar mit $guitarName und eine Drum mit $drumName
// TODO: Übergeben Sie beide an performWith() und geben Sie 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 die OOPKlassen vs. ObjekteDas $this-SchlüsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung