Abstrakte Methoden in Traits
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 54 von 91.
Traits können gebrauchsfertige Methoden bereitstellen, aber manchmal müssen die Klassen, die den Trait verwenden, eine spezifische Funktionalität implementieren. Hier werden abstrakte Methoden in Traits nützlich – sie definieren einen Vertrag, den die verwendende Klasse erfüllen muss.
Wenn ein Trait eine abstrakte Methode deklariert, muss jede Klasse, die diesen Trait verwendet, diese implementieren:
<?php
trait Notifiable {
abstract public function getEmail(): string;
public function sendNotification(string $message): void {
echo "Sending to " . $this->getEmail() . ": $message";
}
}
class User {
use Notifiable;
public function __construct(private string $email) {}
public function getEmail(): string {
return $this->email;
}
}
$user = new User("john@example.com");
$user->sendNotification("Welcome!");
Ausgabe:
Sending to john@example.com: Welcome!Der Trait stellt die Methode sendNotification() bereit, verlässt sich jedoch darauf, dass getEmail() von der Klasse implementiert wird. Dies schafft ein leistungsfähiges Muster, bei dem der Trait die allgemeine Logik übernimmt, während klassenspezifische Details an die implementierende Klasse delegiert werden.
Wenn eine Klasse den Trait verwendet, ohne die abstrakte Methode zu implementieren, wirft PHP einen fatalen Fehler. Dies stellt sicher, dass Traits sicher darauf vertrauen können, dass bestimmte Methoden existieren, was Ihren Code vorhersehbarer und wartbarer macht.
Aufgabe
EinfachLassen Sie uns ein Preissystem aufbauen, bei dem verschiedene Produkttypen ihre Endpreise unterschiedlich berechnen, aber alle eine gemeinsame Rabattlogik über ein Trait mit einer abstrakten Methode teilen.
Sie werden Ihren Code über drei Dateien organisieren:
Discountable.php— Erstellen Sie ein Trait namensDiscountable, das Rabattfunktionen bereitstellt. Das Trait sollte Folgendes enthalten:- Eine abstrakte Methode
getBasePrice(): float, die Klassen, die dieses Trait verwenden, implementieren müssen - Eine Methode
applyDiscount(int $percent), die den Preis nach Anwendung des Rabattprozentsatzes auf den Basispreis berechnet und zurückgibt - Eine Methode
getFinalPrice(int $percent), die einen formatierten String zurückgibt:"Final price: $[discounted_price]"mit 2 Dezimalstellen
- Eine abstrakte Methode
Product.php— Erstellen Sie eineProduct-Klasse, die dasDiscountable-Trait verwendet. Binden Sie die Trait-Datei ein. Verwenden Sie Constructor Promotion, um ein privates$name(string) und ein privates$price(float) zu definieren. Implementieren Sie die erforderliche MethodegetBasePrice(), um den Preis des Produkts zurückzugeben.main.php— Binden Sie die Product-Datei ein. Sie erhalten drei Eingaben: einen Produktnamen, einen Preis und einen Rabattprozentsatz. Erstellen Sie eineProduct-Instanz und geben Sie zwei Zeilen aus:- Den Basispreis, formatiert als
"Base: $[price]"mit 2 Dezimalstellen - Das Ergebnis des Aufrufs von
getFinalPrice()mit dem Rabattprozentsatz
- Den Basispreis, formatiert als
Dieses Muster ist leistungsstark, da das Discountable-Trait von jeder Klasse verwendet werden kann — Produkten, Dienstleistungen, Abonnements —, solange diese getBasePrice() implementieren. Das Trait liefert die gemeinsame Rabattlogik, während jede Klasse definiert, woher ihr Basispreis stammt.
Spickzettel
Traits können abstrakte Methoden deklarieren, die von jeder Klasse, die den Trait verwendet, implementiert werden müssen:
<?php
trait Notifiable {
abstract public function getEmail(): string;
public function sendNotification(string $message): void {
echo "Sending to " . $this->getEmail() . ": $message";
}
}
class User {
use Notifiable;
public function __construct(private string $email) {}
public function getEmail(): string {
return $this->email;
}
}
Der Trait stellt gebrauchsfertige Methoden zur Verfügung, während er von der Klasse verlangt, eine spezifische Funktionalität zu implementieren. Wenn eine Klasse den Trait verwendet, ohne die abstrakte Methode zu implementieren, wirft PHP einen fatalen Fehler.
Dieses Muster ermöglicht es Traits, allgemeine Logik zu verarbeiten, während klassenspezifische Details an die implementierende Klasse delegiert werden.
Probier es selbst
<?php
require_once 'Product.php';
// Eingaben lesen
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$discountPercent = intval(trim(fgets(STDIN)));
// TODO: Erstellen Sie eine Product-Instanz mit dem Namen und dem Preis
// TODO: Geben Sie den Basispreis im Format "Base: $[price]" mit 2 Dezimalstellen aus
// TODO: Geben Sie das Ergebnis des Aufrufs von getFinalPrice() mit dem Rabattprozentsatz 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