Menu
Coddy logo textTech

Konfliktlösung bei Traits

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 53 von 91.

Wenn zwei Traits Methoden mit demselben Namen definieren, wirft PHP einen fatalen Fehler. Sie müssen PHP explizit mitteilen, wie dieser Konflikt zu handhaben ist, indem Sie die Operatoren insteadof und as verwenden.

<?php
trait FileLogger {
    public function log(string $message): void {
        echo "File: $message";
    }
}

trait DatabaseLogger {
    public function log(string $message): void {
        echo "DB: $message";
    }
}

class Application {
    use FileLogger, DatabaseLogger {
        FileLogger::log insteadof DatabaseLogger;
        DatabaseLogger::log as logToDatabase;
    }
}

$app = new Application();
$app->log("Error occurred");
$app->logToDatabase("Error occurred");

Ausgabe:

File: Error occurred
DB: Error occurred

Der insteadof-Operator wählt aus, welche Methode eines Traits verwendet werden soll, wenn ein Konflikt besteht. In diesem Beispiel gewinnt FileLogger::log und wird zur Standard-log()-Methode. Der as-Operator erstellt einen Alias, mit dem Sie auf die Methode des anderen Traits unter einem anderen Namen zugreifen können.

Sie können auch as verwenden, um die Sichtbarkeit einer Methode zu ändern:

<?php
trait Greeting {
    public function sayHello(): void {
        echo "Hello!";
    }
}

class Person {
    use Greeting {
        sayHello as private;
    }
}

Dies macht sayHello() innerhalb der Person-Klasse privat, obwohl sie im Trait public ist. Die Konfliktauflösung bietet Ihnen eine feingranulare Kontrolle darüber, wie Trait-Methoden in Ihre Klassen integriert werden.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Benachrichtigungssystem erstellen, bei dem verschiedene Kanäle Nachrichten senden können. Dabei müssen wir Konflikte lösen, wenn mehrere Traits denselben Methodennamen bereitstellen.

Sie werden Ihren Code über vier Dateien organisieren:

  • EmailNotifier.php — Erstellen Sie einen Trait namens EmailNotifier mit einer Methode notify(string $message), die "Email: [message]" zurückgibt.
  • SmsNotifier.php — Erstellen Sie einen Trait namens SmsNotifier mit einer Methode notify(string $message), die "SMS: [message]" zurückgibt.
  • AlertService.php — Erstellen Sie eine Klasse AlertService, die beide Traits verwendet. Da beide Traits eine notify()-Methode haben, müssen Sie diesen Konflikt lösen:
    • Verwenden Sie EmailNotifier::notify als Standard-notify()-Methode
    • Erstellen Sie einen Alias notifyBySms für die Methode SmsNotifier::notify
    Fügen Sie außerdem eine Methode notifyAll(string $message) hinzu, die beide Benachrichtigungsmethoden aufruft und diese kombiniert auf separaten Zeilen zurückgibt.
  • main.php — Binden Sie alle erforderlichen Dateien ein und erstellen Sie eine AlertService-Instanz. Sie erhalten eine Eingabe: einen Nachrichten-String. Geben Sie drei Zeilen aus:
    • Das Ergebnis des Aufrufs von notify() mit der Nachricht
    • Das Ergebnis des Aufrufs von notifyBySms() mit der Nachricht
    • Das Ergebnis des Aufrufs von notifyAll() mit der Nachricht

Dies zeigt, wie insteadof entscheidet, welche Methode eines Traits bei einem Namenskonflikt gewinnt, während as es Ihnen ermöglicht, den Zugriff auf die Methode des anderen Traits unter einem anderen Namen beizubehalten.

Spickzettel

Wenn mehrere Traits Methoden mit demselben Namen definieren, erfordert PHP eine explizite Konfliktlösung unter Verwendung der Operatoren insteadof und as.

Der Operator insteadof legt fest, welche Methode eines Traits standardmäßig verwendet werden soll:

<?php
trait FileLogger {
    public function log(string $message): void {
        echo "File: $message";
    }
}

trait DatabaseLogger {
    public function log(string $message): void {
        echo "DB: $message";
    }
}

class Application {
    use FileLogger, DatabaseLogger {
        FileLogger::log insteadof DatabaseLogger;
        DatabaseLogger::log as logToDatabase;
    }
}

$app = new Application();
$app->log("Error occurred"); // File: Error occurred
$app->logToDatabase("Error occurred"); // DB: Error occurred

Der Operator as erstellt einen Alias für eine Trait-Methode und ermöglicht so den Zugriff unter einem anderen Namen.

Sie können as auch verwenden, um die Sichtbarkeit einer Methode zu ändern:

<?php
trait Greeting {
    public function sayHello(): void {
        echo "Hello!";
    }
}

class Person {
    use Greeting {
        sayHello as private;
    }
}

Probier es selbst

<?php
require_once 'AlertService.php';

// Eingabe lesen
$message = trim(fgets(STDIN));

// TODO: Eine AlertService-Instanz erstellen

// TODO: Das Ergebnis des Aufrufs von notify() mit der Nachricht ausgeben

// TODO: Das Ergebnis des Aufrufs von notifyBySms() mit der Nachricht ausgeben

// TODO: Das Ergebnis des Aufrufs von notifyAll() mit der Nachricht ausgeben
?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung