Вопрос по php, oop – Расширять черты с помощью классов в PHP?

24

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

Например:

<code>Trait T { }

Class C use T {}
/* or */
Class C extends T {}
</code>

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

Как быClass C use T {} отличаться от того, что у нас уже есть (кроме немного другого синтаксиса)? Jon
Укороченный синтаксис, когда я хочу расширить некоторый класс из базового класса, но с использованием черт (ов). Meglio
О, я только что обнаружил, что мы можем просто сделать: Класс C {использовать T} - выглядит достаточно ясным и коротким. Meglio
@ Meglio: Просто сделай это:Class C extends Base {use T }. hakre

Ваш Ответ

3   ответа
5

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

@Meglio: синтаксис не имеет длины, поэтому нет более короткого синтаксиса.
Короче обозначение. Meglio
@ JustMartin посмотри мой ответ
Идея здесь в том, чтобы использовать более короткий синтаксис, а не способ фактически расширять черты. Meglio
Но что делать, если у меня есть какой-то сторонний фреймворк (точнее, Laravel) и мне нужна одна из его черт, но с небольшим исправлением для одной функции, которая помечена какprotected в черту? Я не хочу менять код Laravel, поэтому было бы здорово иметь какой-нибудь способ переопределить этот защищенный метод в моем собственном качестве. Чтобы быть более конкретным, проблема заключается в жестко закодированной текстовой строке, которую я хочу локализовать.
35

Руководство по PHP гласит:

Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance and 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

14

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

Похожие вопросы