web-dev-qa-db-ja.com

PHPのクラスで特性を拡張しますか?

PHPのクラスを使用して特性を拡張できないのはなぜですか?

例えば:

Trait T { }

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

そのような構文の潜在的な競合はありますか?そうは思わない。

31
Meglio

PHPマニュアルの状態はこうして:

トレイトは、PHPなどの単一継承言語でコードを再利用するためのメカニズムです。特性は、開発者が異なるクラス階層にあるいくつかの独立したクラスでメソッドのセットを自由に再利用できるようにすることで、単一継承のいくつかの制限を減らすことを目的としています。トレイトとクラスの組み合わせのセマンティクスは、複雑さを軽減し、多重継承とミックスインに関連する一般的な問題を回避する方法で定義されます。

トレイトを拡張する場合は、おそらくクラスにする必要があります。あるクラスに他のクラスで使用したいメソッドのセットがあるが、クラスを拡張するのが不適切だと感じる場合(例: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

36
mrlee

特性をいくらか拡張できます。 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
19
andrewtweber

拡張できるのはクラスだけです。特性はnotクラスです。これらはクラスで使用/インクルードできますが、それ自体はクラスではありません。トレイトを拡張する必要があると思われる場合、それはおそらくクラスではなく、おそらく抽象クラスであり、トレイトではないはずです。

6
John Conde