Verwendung mehrerer Traits
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 52 von 91.
Ein einzelnes Trait ist nützlich, aber die wahre Stärke zeigt sich, wenn man mehrere Traits in einer Klasse kombiniert. PHP ermöglicht es Ihnen, so viele Traits einzubinden, wie Sie benötigen, wodurch Ihre Klasse Funktionen aus mehreren Quellen gleichzeitig erhält.
Um mehrere Traits zu verwenden, listen Sie diese einfach durch Kommas getrennt nach dem use-Schlüsselwort auf:
<?php
trait Timestampable {
public function getTimestamp(): string {
return date('Y-m-d H:i:s');
}
}
trait Identifiable {
private string $id;
public function generateId(): void {
$this->id = uniqid('id_');
}
public function getId(): string {
return $this->id;
}
}
class Post {
use Timestampable, Identifiable;
public function __construct(public string $title) {
$this->generateId();
}
}
$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
Ausgabe:
id_6789abc123 - 2024-01-15 10:30:00Die Klasse Post verfügt nun über Methoden aus beiden Traits. Jeder Trait trägt seine eigene Funktionalität bei – Timestampable stellt zeitbezogene Methoden bereit, während Identifiable eindeutige IDs verarbeitet. Dieser Ansatz sorgt dafür, dass jeder Trait auf eine einzige Verantwortlichkeit konzentriert bleibt, was Ihren Code modularer und wiederverwendbarer macht.
Was passiert, wenn zwei Traits Methoden mit demselben Namen haben? Das ist eine Konfliktsituation, die wir in der nächsten Lektion untersuchen werden.
Aufgabe
EinfachLassen Sie uns ein Produktmanagementsystem aufbauen, das mehrere Traits kombiniert, um Produkten sowohl Preis- als auch Bestandsfunktionen zu verleihen. Jeder Trait wird eine einzelne Aufgabe übernehmen, und Ihre Produktklasse wird die Funktionalität von beiden erhalten.
Sie werden Ihren Code über drei Dateien organisieren:
Priceable.php— Erstellen Sie einen Trait namensPriceable, der die Preisfunktionalität verwaltet. Der Trait sollte Folgendes enthalten:- Eine private Eigenschaft
$price(float) - Eine Methode
setPrice(float $price), die den Preis speichert - Eine Methode
getPrice(), die den Preis zurückgibt - Eine Methode
getFormattedPrice(), die den Preis formatiert als"$[price]"mit 2 Dezimalstellen zurückgibt
- Eine private Eigenschaft
Stockable.php— Erstellen Sie einen Trait namensStockable, der den Bestand verwaltet. Der Trait sollte Folgendes enthalten:- Eine private Eigenschaft
$stock(integer) - Eine Methode
setStock(int $quantity), die die Bestandsmenge speichert - Eine Methode
getStock(), die den aktuellen Bestand zurückgibt - Eine Methode
isInStock(), dietruezurückgibt, wenn der Bestand größer als 0 ist, andernfallsfalse
- Eine private Eigenschaft
main.php— Binden Sie beide Trait-Dateien ein und erstellen Sie eineProduct-Klasse, die sowohl denPriceable- als auch denStockable-Trait verwendet. Nutzen Sie Constructor Promotion, um eine öffentliche$name-Eigenschaft zu definieren. Der Konstruktor sollte außerdem einen Preis und eine Bestandsmenge akzeptieren und die Trait-Methoden verwenden, um diese zu setzen.Sie erhalten drei Eingaben: einen Produktnamen, einen Preis und eine Bestandsmenge. Erstellen Sie ein Produkt mit diesen Werten und geben Sie vier Zeilen aus:
- Den Produktnamen
- Den formatierten Preis (unter Verwendung von
getFormattedPrice()) - Die Bestandsmenge
"Available", wenn auf Lager, oder"Out of stock", wenn nicht
Dies zeigt, wie mehrere Traits zusammenarbeiten — Ihre Product-Klasse erhält Preisfunktionen von einem Trait und Bestandsverwaltung von einem anderen, wodurch jede Aufgabe sauber getrennt bleibt, während sie zu einem voll funktionsfähigen Produkt kombiniert werden.
Spickzettel
Um mehrere Traits in einer Klasse zu verwenden, listen Sie diese durch Kommas getrennt nach dem Schlüsselwort use auf:
<?php
trait Timestampable {
public function getTimestamp(): string {
return date('Y-m-d H:i:s');
}
}
trait Identifiable {
private string $id;
public function generateId(): void {
$this->id = uniqid('id_');
}
public function getId(): string {
return $this->id;
}
}
class Post {
use Timestampable, Identifiable;
public function __construct(public string $title) {
$this->generateId();
}
}
$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
// Ausgabe: id_6789abc123 - 2024-01-15 10:30:00
Jeder Trait trägt seine eigene Funktionalität zur Klasse bei. Dieser Ansatz sorgt dafür, dass jeder Trait auf eine einzige Verantwortlichkeit fokussiert bleibt, was den Code modularer und wiederverwendbarer macht.
Probier es selbst
<?php
require_once 'Priceable.php';
require_once 'Stockable.php';
// TODO: Erstellen Sie eine Product-Klasse, die sowohl Priceable- als auch Stockable-Traits verwendet
// Verwenden Sie Constructor Promotion für die öffentliche Eigenschaft $name
// Der Konstruktor sollte Name, Preis und Bestand akzeptieren und Trait-Methoden verwenden, um Preis und Bestand festzulegen
class Product {
// TODO: Verwenden Sie hier die Traits
// TODO: Implementieren Sie den Konstruktor mit Constructor Promotion für $name
// und legen Sie Preis und Bestand mithilfe von Trait-Methoden fest
}
// Eingabe lesen
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));
// TODO: Erstellen Sie eine Product-Instanz mit den Eingabewerten
// TODO: Geben Sie den Produktnamen aus
// TODO: Geben Sie den formatierten Preis mit getFormattedPrice() aus
// TODO: Geben Sie die Bestandsmenge aus
// TODO: Geben Sie "Available" aus, wenn auf Lager, oder "Out of stock", wenn nicht
?>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