Почему нам не разрешено расширять черты с помощью классов в PHP?
Например:
Trait T { } Class C use T {} /* or */ Class C extends T {}
Есть ли какой-либо потенциальный конфликт для такого синтаксиса? Я так не думаю.
В руководстве PHP указано:
Черты – это механизм повторного использования кода в отдельных языках наследования, таких как PHP. Предел предназначен для уменьшения некоторых ограничений одиночного наследования, позволяя разработчику свободно использовать множество методов в нескольких независимых классах, живущих в разных иерархиях классов. Семантика комбинации признаков и классов определяется таким образом, который уменьшает сложность и позволяет избежать типичных проблем, связанных с множественным наследованием и Mixins.
Если вы хотите расширить черту, то это, вероятно, должен быть класс. Если у вас есть набор методов в одном классе, которые вы хотите использовать в других, но неудобно расширять класс (например, class Animal extends Vehicle
), то в PHP 5.4 он может хорошо работать как признак.
Чтобы ответить на вопрос более прямо, вы не «расширяете» черту, но можете создавать черты, которые сами используют другие черты. Согласно руководству PHP:
trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World!'; } } trait HelloWorld { use Hello, World; } class MyHelloWorld { use HelloWorld; }
Вы можете рассматривать это как способ сохранить свои черты в логических группах и ввести некоторую модульность.
Изменить: увидев некоторые комментарии, я считаю, что стоит отметить, что использование признака в базовом классе также означает, что черта присутствует в любом классе, который ее расширяет, а функции признака имеют приоритет над базовым классом ». Помещение его в дочерний класс просто сделает функции признака недоступными для родительского / базового класса.
Parent > Trait > Child
Вы можете несколько расширять черты. Расширяясь в ответе mrlee, когда вы use
черту, вы можете переименовать ее методы.
Скажем, например, у вас есть «родительский» признак, который был определен вашей каркасом:
trait FrameworkTrait { public function keepMe() { // Framework's logic that you want to keep } public function replaceMe() { // Framework's logic that you need to overwrite } }
Просто потяните родительский признак, переименуйте его метод replaceMe
на что-то еще и определите свой собственный метод replaceMe
.
trait MyTrait { use FrameworkTrait { FrameworkTrait::replaceMe as frameworkReplaceMe; } public function replaceMe() { // You can even call the "parent" method if you'd like: $this->frameworkReplaceMe(); // Your logic here } }
И затем в вашем классе:
class MyClass { use MyTrait; }
Теперь объекты этого класса могут сделать это:
$obj = new MyClass(); $obj->keepMe(); // calls "parent" trait $obj->replaceMe(); // calls "child" trait $obj->frameworkReplaceMe(); // calls "parent" trait
Только классы могут быть расширены. Черты не классы. Они могут быть использованы / включены классами, но не являются самими классами. Если вы считаете, что черта должна быть расширена, она, вероятно, должна быть классом, вероятно абстрактным, а не признаком.