Почему нам не разрешено расширять черты с помощью классов в PHP?
Например:
Trait T { }
Class C use T {}
/* or */
Class C extends T {}
Есть ли какой-либо потенциальный конфликт для такого синтаксиса? Я так не думаю.
Почему нам не разрешено расширять черты с помощью классов в 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 logic that you want to keep
}
public function replaceMe() {
// Framework 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
Только классы могут быть расширены. Черты не классы. Они могут быть использованы/включены классами, но не являются самими классами. Если вы считаете, что черта должна быть расширена, она, вероятно, должна быть классом, вероятно абстрактным, а не чертой.