Die wirklich kurze Version ist einfacher, weil Sie nicht können. So funktionieren Eigenschaften nicht.
Wenn Sie use SomeTrait;
in PHP schreiben , weisen Sie den Compiler (effektiv) an, den Code aus dem Merkmal zu kopieren und in die Klasse einzufügen, in der er verwendet wird.
Da sich das use SomeTrait;
innerhalb der Klasse befindet, kann es nicht implements SomeInterface
zur Klasse hinzugefügt werden , da dies außerhalb der Klasse liegen muss.
"Warum sind in PHP keine Traits-Typen?"
Weil sie nicht instanziiert werden können. Merkmale sind eigentlich nur ein Sprachkonstrukt (das den Compiler anweist, den Merkmalcode zu kopieren und in diese Klasse einzufügen), im Gegensatz zu einem Objekt oder Typ, auf das Ihr Code verweisen kann.
Also möchte ich im Code "entwerfen", dass jede Klasse, die mein Merkmal verwenden möchte, die Schnittstelle implementieren muss.
Dies kann erzwungen werden, indem eine abstrakte Klasse für use
das Merkmal verwendet und dann Klassen daraus erweitert werden.
interface SomeInterface{
public function someInterfaceFunction();
}
trait SomeTrait {
function sayHello(){
echo "Hello my secret is ".static::$secret;
}
}
abstract class AbstractClass implements SomeInterface{
use SomeTrait;
}
class TestClass extends AbstractClass {
static public $secret = 12345;
//function someInterfaceFunction(){
//Trying to instantiate this class without this function uncommented will throw an error
//Fatal error: Class TestClass contains 1 abstract method and must therefore be
//declared abstract or implement the remaining methods (SomeInterface::doSomething)
//}
}
$test = new TestClass();
$test->sayHello();
Wenn Sie jedoch durchsetzen müssen, dass eine Klasse, die ein Merkmal verwendet, eine bestimmte Methode hat, verwenden Sie möglicherweise Merkmale, bei denen Sie eigentlich abstrakte Klassen sein sollten.
Oder dass Sie Ihre Logik falsch herum haben. Sie sollten Klassen benötigen, die Schnittstellen implementieren, die bestimmte Funktionen haben, und nicht, dass sie sich selbst als Implementierung einer Schnittstelle deklarieren müssen, wenn sie bestimmte Funktionen haben.
Bearbeiten
Tatsächlich können Sie abstrakte Funktionen in Traits definieren, um eine Klasse zur Implementierung der Methode zu zwingen. z.B
trait LoggerTrait {
public function debug($message, array $context = array()) {
$this->log('debug', $message, $context);
}
abstract public function log($level, $message, array $context = array());
}
Dies erlaubt Ihnen jedoch immer noch nicht, die Schnittstelle in das Merkmal zu implementieren, und riecht immer noch nach einem schlechten Design, da Schnittstellen viel besser sind als Merkmale bei der Definition eines Vertrags, den eine Klasse erfüllen muss.