Das final Schlüsselwort
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 24 von 91.
Während Vererbung und das Überschreiben von Methoden Flexibilität bieten, müssen Sie manchmal verhindern, dass bestimmte Klassen oder Methoden geändert werden. Das Schlüsselwort final sperrt Ihren Code ab und stellt sicher, dass spezifische Implementierungen nicht durch Kindklassen geändert werden können.
Wenn Sie eine Methode als final markieren, kann keine Kindklasse diese überschreiben:
<?php
class BankAccount {
protected $balance;
public function __construct($balance) {
$this->balance = $balance;
}
final public function getAccountId() {
return "ACC-" . spl_object_id($this);
}
}
class SavingsAccount extends BankAccount {
public function addInterest() {
return $this->balance * 0.05;
}
}
$account = new SavingsAccount(1000);
echo $account->getAccountId();
Ausgabe:
ACC-1Die Methode getAccountId() kann in SavingsAccount oder einer anderen untergeordneten Klasse nicht überschrieben werden. Dies schützt kritische Funktionen, die über alle Kontotypen hinweg konsistent bleiben müssen.
Sie können auch eine gesamte Klasse als final markieren, um jegliche Vererbung zu verhindern:
<?php
final class SecurityManager {
public function authenticate($user) {
return "Authenticating $user";
}
}
$security = new SecurityManager();
echo $security->authenticate("admin");
Ausgabe:
Authenticating adminKeine Klasse kann SecurityManager erweitern. Dies ist nützlich für sicherheitsrelevante Klassen oder wenn das Klassendesign abgeschlossen ist und nicht mehr geändert werden sollte.
Wichtiger Punkt: Verwenden Sie final bei Methoden, um das Überschreiben zu verhindern, während Vererbung weiterhin zulässig bleibt, oder bei Klassen, um Vererbung gänzlich zu unterbinden. Es ist ein Werkzeug zum Schutz von kritischem Code, der genau wie entworfen funktionieren muss.
Aufgabe
EinfachLassen Sie uns ein Dokumentenmanagementsystem erstellen, das demonstriert, wie das Schlüsselwort final kritische Funktionen davor schützt, von Kindklassen geändert zu werden.
Sie werden drei Dateien erstellen, die zusammenarbeiten, um verschiedene Dokumenttypen zu verwalten und gleichzeitig sicherzustellen, dass bestimmte Sicherheitsfunktionen gesperrt bleiben:
Document.php— Definieren Sie eine KlasseDocument, die als Basis für alle Dokumente dient. Sie sollte eine öffentliche Eigenschaft$titleund eine geschützte Eigenschaft$authorhaben. Der Konstruktor akzeptiert sowohl den Titel als auch den Autor. Fügen Sie einefinalMethode namensgetSignature()hinzu, die"Signed by: "gefolgt vom Autor zurückgibt — dieses Sicherheitsmerkmal darf niemals von Kindklassen geändert werden. Fügen Sie außerdem eine reguläre MethodegetContent()hinzu, die"Document: "gefolgt vom Titel zurückgibt.Report.php— Definieren Sie eine KlasseReport, dieDocumenterweitert. Binden Sie die Datei Document am Anfang ein. Diese Klasse fügt eine Eigenschaft$departmenthinzu. Der Konstruktor sollte Titel, Autor und Abteilung akzeptieren — verwenden Sieparent::__construct()für die ersten beiden und setzen Sie dann die Abteilung. Überschreiben Sie die MethodegetContent(), sodass sie"Report: "gefolgt vom Titel und der Abteilung in Klammern (z. B."Report: [title] ([department])") zurückgibt. Die KlasseReporterbt die finale MethodegetSignature(), ohne sie ändern zu können.main.php— Binden Sie die Datei Report ein. Sie erhalten drei Eingaben: den Dokumenttitel, den Namen des Autors und die Abteilung. Erstellen Sie einReport-Objekt mit diesen Werten. Geben Sie das Ergebnis vongetContent()in der ersten Zeile aus und das Ergebnis vongetSignature()in der zweiten Zeile.
Diese Herausforderung zeigt, wie final Methoden kritische Funktionen schützen — die Signaturerstellung bleibt über alle Dokumenttypen hinweg konsistent, während andere Methoden wie getContent() von jeder Kindklasse angepasst werden können. Der Report kann ändern, wie der Inhalt angezeigt wird, aber das Signaturformat ist in der Elternklasse festgeschrieben.
Spickzettel
Das Schlüsselwort final verhindert, dass Klassen oder Methoden von Kindklassen geändert werden.
Finale Methoden: Markieren Sie eine Methode als final, um zu verhindern, dass Kindklassen sie überschreiben:
<?php
class BankAccount {
protected $balance;
final public function getAccountId() {
return "ACC-" . spl_object_id($this);
}
}
class SavingsAccount extends BankAccount {
// getAccountId() kann nicht überschrieben werden
}
Finale Klassen: Markieren Sie eine gesamte Klasse als final, um jegliche Vererbung zu verhindern:
<?php
final class SecurityManager {
public function authenticate($user) {
return "Authenticating $user";
}
}
// Keine Klasse kann SecurityManager erweitern
Verwenden Sie final bei Methoden, um bestimmte Funktionalitäten zu schützen, während Vererbung weiterhin möglich ist, oder bei Klassen, um Vererbung gänzlich zu unterbinden. Dies ist nützlich für sicherheitsrelevante Codes oder wenn Implementierungen konsistent bleiben müssen.
Probier es selbst
<?php
require_once 'Report.php';
// Eingabe lesen
$title = trim(fgets(STDIN));
$author = trim(fgets(STDIN));
$department = trim(fgets(STDIN));
// TODO: Erstellen Sie ein Report-Objekt mit den Eingabewerten
// TODO: Geben Sie das Ergebnis von getContent() aus
// TODO: Geben Sie das Ergebnis von getSignature() aus
?>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