Подтвердить что ты не робот

Расширять черты с классами в PHP?

Почему нам не разрешено расширять черты с помощью классов в PHP?

Например:

Trait T { }

Class C use T {}
/* or */
Class C extends T {}

Есть ли какой-либо потенциальный конфликт для такого синтаксиса? Я так не думаю.

4b9b3361

Ответ 1

В руководстве 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

http://php.net/manual/en/language.oop5.traits.php

Ответ 2

Вы можете немного расширить черты. Расширяясь при ответе на 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

Ответ 3

Только классы могут быть расширены. Черты не классы. Они могут быть использованы/включены классами, но не являются самими классами. Если вы считаете, что черта должна быть расширена, она, вероятно, должна быть классом, вероятно абстрактным, а не чертой.