24

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

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

Например:

Trait T { }

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

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

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

    от
  • @ JustMartin посмотри мой ответ

    от
  • Идея здесь в том, чтобы использовать более короткий синтаксис, а не способ фактически расширять черты.

    от Meglio
  • @Meglio: синтаксис не имеет длины, поэтому нет более короткого синтаксиса.

    от
  • Короче обозначение.

    от Meglio
  • О, я только что обнаружил, что мы можем просто сделать: Класс C {использовать T} - выглядит достаточно ясным и коротким.

    от Meglio
  • Укороченный синтаксис, когда я хочу расширить некоторый класс из базового класса, но с использованием черт (ов).

    от Meglio
  • @ Meglio: Просто сделай это:Class C extends Base {use T }.

    от hakre
  • Как быClass C use T {} отличаться от того, что у нас уже есть (кроме немного другого синтаксиса)?

    от Jon
  • 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
    

  • 5

    Только классы могут быть расширены. Чертыnot 

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

  • 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