PHPのTraitsの詳細

5246 ワード

PHPは単一継承言語であり、PHP 5.4 Traitsが現れるまでPHPのクラスは2つのベースクラスから属性またはメソッドを同時に継承することはできません.phpのTraitsとGo言語の組合せ機能は類似しており、クラスでuseキーワードを使用して組合せたいTrait名を宣言し、特定のTraitの宣言でtraitキーワードを使用することで、Traitを直接インスタンス化することはできません.具体的な使い方は以下のコードを見てください.

carName}
"; } } class Person { public function eat() { echo "eat
"; } } class Student extends Person { use Drive; public function study() { echo "study
"; } } $student = new Student(); $student->study(); $student->eat(); $student->driving();

出力結果は次のとおりです.

study
eat
driving trait

上の例では、StudioクラスはPersonを継承することによってeatメソッドがあり、Driveを組み合わせることによってdrivingメソッドと属性carNameがあります.
Trait、ベースクラス、およびこのクラスに同じ名前のプロパティまたはメソッドが存在する場合、最終的にはどちらが保持されますか?次のコードでテストします.

";
    }
    public function driving() {
      echo "driving from drive
"; } } class Person { public function hello() { echo "hello person
"; } public function driving() { echo "driving from person
"; } } class Student extends Person { use Drive; public function hello() { echo "hello student
"; } } $student = new Student(); $student-?>hello(); $student->driving();

出力結果は次のとおりです.

hello student
driving from drive

したがって,メソッドまたは属性が同名の場合,現在のクラスのメソッドはtraitのメソッドを上書きし,traitのメソッドはベースクラスのメソッドを上書きすると結論した.
複数のTraitを結合する場合は、Trait名をカンマで区切ります.
use Trait1, Trait2;
複数のTraitに同じ名前のメソッドまたは属性が含まれている場合、どうなりますか?答えは、複数のTraitが同じ名前のプロパティまたはメソッドを含む場合、競合の解決を明確に宣言する必要があります.そうしないと、致命的なエラーが発生します.

";
  }
  public function hi() {
    echo "Trait1::hi
"; } } trait Trait2 { public function hello() { echo "Trait2::hello
"; } public function hi() { echo "Trait2::hi
"; } } class Class1 { use Trait1, Trait2; }

出力結果は次のとおりです.

PHP Fatal error: Trait method hello has not been applied, because there are collisions with other trait methods on Class1 in ~/php54/trait_3.php on line 20

衝突を解決するにはinsteadofオペレータとasオペレータを使用します.insteadofは別のメソッドの代わりにメソッドを使用します.asはメソッドに別名を付けます.具体的な使い方はコードを参照してください.

";
  }
  public function hi() {
    echo "Trait1::hi
"; } } trait Trait2 { public function hello() { echo "Trait2::hello
"; } public function hi() { echo "Trait2::hi
"; } } class Class1 { use Trait1, Trait2 { Trait2::hello insteadof Trait1; Trait1::hi insteadof Trait2; } } class Class2 { use Trait1, Trait2 { Trait2::hello insteadof Trait1; Trait1::hi insteadof Trait2; Trait2::hi as hei; Trait1::hello as hehe; } } $Obj1 = new Class1(); $Obj1-?>hello(); $Obj1->hi(); echo "
"; $Obj2 = new Class2(); $Obj2->hello(); $Obj2->hi(); $Obj2->hei(); $Obj2->hehe();

出力結果は次のとおりです.

Trait2::hello
Trait1::hi

Trait2::hello
Trait1::hi
Trait2::hi
Trait1::hello


Asキーワードにはもう一つの用途があります.それは修正方法のアクセス制御です.

";
    }
  }
  class Class1 {
    use Hello {
      hello as protected;
    }
  }
  class Class2 {
    use Hello {
      Hello::hello as private hi;
    }
  }
  $Obj1 = new Class1();
  $Obj1-?>hello(); #      ,  hello          
  $Obj2 = new Class2();
  $Obj2->hello(); #    hello        
  $Obj2->hi(); #      ,    hi         

TraitもTraitを組み合わせることができ、Traitでは抽象的な方法、静的属性、静的方法をサポートし、テストコードは以下の通りである.

";
  }
}
trait World {
  use Hello;
  public function sayWorld() {
    echo "World
"; } abstract public function getWorld(); public function inc() { static $c = 0; $c = $c + 1; echo "$c
"; } public static function doSomething() { echo "Doing something
"; } } class HelloWorld { use World; public function getWorld() { return 'get World'; } } $Obj = new HelloWorld(); $Obj-?>sayHello(); $Obj->sayWorld(); echo $Obj->getWorld() . "
"; HelloWorld::doSomething(); $Obj->inc(); $Obj->inc();

出力結果は次のとおりです.

Hello
World
get World
Doing something
1
2

以上が本文のすべての内容で、みんなの学習に役立つことを望みます.