Abstrakte Methoden in Traits
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 54 von 91.
Traits können sofort einsatzbereite Methoden bereitstellen, aber manchmal muss die Klasse, die den Trait verwendet, eine bestimmte Funktionalität implementieren. Hier kommen abstrakte Methoden in Traits zum Einsatz – 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, sie 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!Das Trait stellt die Methode sendNotification() bereit, ist jedoch darauf angewiesen, dass getEmail() von der Klasse implementiert wird. Dadurch entsteht ein leistungsstarkes Muster, bei dem das Trait die allgemeine Logik übernimmt und klassenspezifische Details an die implementierende Klasse delegiert.
Wenn eine Klasse das Trait verwendet, ohne die abstrakte Methode zu implementieren, löst PHP einen schwerwiegenden Fehler aus. Dadurch wird sichergestellt, dass Traits sicher davon ausgehen können, dass bestimmte Methoden vorhanden sind, wodurch dein Code vorhersehbarer und leichter wartbar wird.
Aufgabe
EinfachErstellen wir ein Preissystem, in dem verschiedene Produkttypen ihre Endpreise unterschiedlich berechnen, aber alle gemeinsame Rabattlogik über ein Trait mit einer abstrakten Methode verwenden.
Du organisierst deinen Code über drei Dateien:
Discountable.php: Erstelle 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 Grundpreis 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: Erstelle eineProduct-Klasse, die dasDiscountable-Trait verwendet. Binde die Trait-Datei ein. Verwende Konstruktor-Promotion, um einen privaten$name-Wert (string) und einen privaten$price-Wert (float) zu definieren. Implementiere die erforderliche MethodegetBasePrice(), sodass sie den Preis des Produkts zurückgibt.main.php: Binde die Product-Datei ein. Du erhältst drei Eingaben: einen Produktnamen, einen Preis und einen Rabattprozentsatz. Erstelle eineProduct-Instanz und gib zwei Zeilen aus:- Den formatierten Grundpreis als
"Base: $[price]"mit 2 Dezimalstellen - Das Ergebnis des Aufrufs von
getFinalPrice()mit dem Rabattprozentsatz
- Den formatierten Grundpreis als
Dieses Muster ist leistungsfähig, weil das Discountable-Trait von jeder Klasse verwendet werden kann – von Produkten, Diensten und Abonnements –, solange sie getBasePrice() implementieren. Das Trait stellt die gemeinsame Rabattlogik bereit, während jede Klasse definiert, woher ihr Grundpreis stammt.
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: Erstelle eine Product-Instanz mit dem Namen und dem Preis
// TODO: Gib den Basispreis formatiert als "Base: $[price]" mit 2 Dezimalstellen aus
// TODO: Gib 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 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