Traits in PHP5.4 is a newly introduced feature used to implement code reuse. Let's take a look at the example of code reuse using traits in PHP. I hope the article will help you. traits in PHP 5.4 is a new feature used to implement code reuse. Let's take a look at the example of code reuse using traits in PHP. I hope the article will help you.
Script ec (2); script
After PHP5.4, a new traits implementation code reuse mechanism is added. Trait is similar to a class, but it cannot be instantiated. Without inheritance, you only need to use the keyword use in the class to introduce multiple Traits, separated by commas.
(1) simple use of Trait
Trait {
Public $ var1 = 'test1 ';
Public function test1 (){
Echo 'trait A: test1 ()';
}
}
Trait B {
Public $ var2 = 'test2 ';
Public function test2 (){
Echo 'trait B: test2 ()';
}
}
Class C {
Use A, B;
}
$ C = new C ();
Echo $ c-> var1; // test1
$ C-> test2 (); // trait B: test2 ()
(2) Priority
Trait will overwrite the inherited method, and the current class will overwrite the Trait method.
Trait {
Public $ var1 = 'test ';
Public function test (){
Echo 'a: test ()';
}
Public function test1 (){
Echo 'a: test1 ()';
}
}
Class B {
Public function test (){
Echo 'B: test ()';
}
Public function test1 (){
Echo 'B: test1 ()';
}
}
Class C extends B {
Use;
Public function test (){
Echo 'C: test ()';
}
}
$ C = new C ();
$ C-> test (); // c: test ()
$ C-> test1 (); // A: test1 ()
(3) Multiple Trait conflicts
If the conflict is not resolved, a fatal error occurs;
Insteadof can be used to determine which method of conflict is used;
Use the as operator to name one of the conflicting methods;
Trait {
Public function test (){
Echo 'a: test ()';
}
}
Trait B {
Public function test (){
Echo 'B: test ()';
}
}
Class C {
Use A, B {
B: test insteadof;
B: test as t;
}
}
$ C = new C ();
$ C-> test (); // B: test ()
$ C-> t (); // B: test () can be named as another one.
(4) as can be used to modify method Access Control
Trait HelloWorld {
Public function sayHello (){
Echo 'Hello World! ';
}
}
// Modify the access control of sayHello
Class {
Use HelloWorld {sayHello as protected ;}
}
// Give the method an alias that changes the access control.
// The access control of the original sayHello version is not changed.
Class B {
Use HelloWorld {sayHello as private myPrivateHello ;}
}
$ B = new ();
$ B-> sayHello (); // Fatal error: Call to protected method A: sayHello () from context''
(5) Use Trait in Trait
Trait {
Public function test1 (){
Echo 'test1 ';
}
}
Trait B {
Public function test2 (){
Echo 'test2 ';
}
}
Trait C {
Use A, B;
}
Class D {
Use C;
}
$ D = new D ();
$ D-> test2 (); // test2
(6) Trait supports abstract methods, static methods, and cannot directly define static variables. However, static variables can be referenced by the trait method.
Trait {
Public function test1 (){
Static $ a = 0;
$ A ++;
Echo $;
}
Abstract public function test2 (); // definable abstract Method
}
Class B {
Use;
Public function test2 (){
}
}
$ B = new B ();
$ B-> test1 (); // 1
$ B-> test1 (); // 2
(7) Trait can define attributes, but the same name attribute cannot be defined in the class.
Trait {
Public $ test1;
}
Class B {
Use;
Public $ test2;
}
See
Trait Drive {
Public $ carName = 'trait ';
Public function driving (){
Echo "driving {$ this-> carName} \ n ";
}
}
Class Person {
Public function eat (){
Echo "eat \ n ";
}
}
Class Student extends Person {
Use Drive;
Public function study (){
Echo "study \ n ";
}
}
$ Student = new Student ();
$ Student-> study ();
$ Student-> eat ();
$ Student-> driving ();
The output result is as follows:
Study
Eat
Driving trait
In the preceding example, the Student class inherits the Person, has the eat method, and combines Drive with the driving method and the carName attribute.
Which of the following attributes or methods will be retained if Trait, base class, and current class have an attribute or method of the same name? Test the following code:
Trait Drive {
Public function hello (){
Echo "hello drive \ n ";
}
Public function driving (){
Echo "driving from drive \ n ";
}
}
Class Person {
Public function hello (){
Echo "hello person \ n ";
}
Public function driving (){
Echo "driving from person \ n ";
}
}
Class Student extends Person {
Use Drive;
Public function hello (){
Echo "hello student \ n ";
}
}
$ Student = new Student ();
$ Student-> hello ();
$ Student-> driving ();
The output result is as follows:
Hello student
Driving from drive
Therefore, it is concluded that when the method or attribute has the same name, the method in the current class will overwrite the trait method, and the trait method overwrites the method in the base class.
If you want to combine multiple Trait, use commas to separate the Trait names:
Use Trait1, Trait2;
What if multiple Trait nodes contain methods or attributes with the same name? The answer is that when multiple Trait combinations contain attributes or methods of the same name, you need to explicitly resolve the conflict. Otherwise, a fatal error will occur.
Trait Trait1 {
Public function hello (){
Echo "Trait1: hello \ n ";
}
Public function hi (){
Echo "Trait1: hi \ n ";
}
}
Trait Trait2 {
Public function hello (){
Echo "Trait2: hello \ n ";
}
Public function hi (){
Echo "Trait2: hi \ n ";
}
}
Class Class1 {
Use Trait1, Trait2;
}
The output result is as follows:
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
Use the insteadof and as operators to resolve conflicts. insteadof uses a method to replace the other, while as uses an alias for the method. For specific usage, see the code:
Trait Trait1 {
Public function hello (){
Echo "Trait1: hello \ n ";
}
Public function hi (){
Echo "Trait1: hi \ n ";
}
}
Trait Trait2 {
Public function hello (){
Echo "Trait2: hello \ n ";
}
Public function hi (){
Echo "Trait2: hi \ n ";
}
}
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 "\ n ";
$ Obj2 = new Class2 ();
$ Obj2-> hello ();
$ Obj2-> hi ();
$ Obj2-> hei ();
$ Obj2-> hehe ();
The output result is as follows:
Trait2: hello
Trait1: hi
Trait2: hello
Trait1: hi
Trait2: hi
Trait1: hello
The as keyword has another purpose, that is, the access control of the modification method:
Trait Hello {
Public function hello (){
Echo "hello, trait \ n ";
}
}
Class Class1 {
Use Hello {
Hello as protected;
}
}
Class Class2 {
Use Hello {
Hello: hello as private hi;
}
}
$ Obj1 = new Class1 ();
$ Obj1-> hello (); # a fatal error is reported because the hello method is modified to a protected
$ Obj2 = new Class2 ();
$ Obj2-> hello (); # The original hello method is still public
$ Obj2-> hi (); # a fatal error is reported because the alias hi method is changed to private
Trait can also be combined with Trait. Trait supports abstract methods, static attributes, and static methods. The test code is as follows:
Trait Hello {
Public function sayHello (){
Echo "Hello \ n ";
}
}
Trait World {
Use Hello;
Public function sayWorld (){
Echo "World \ n ";
}
Abstract public function getWorld ();
Public function inc (){
Static $ c = 0;
$ C = $ c + 1;
Echo "$ c \ n ";
}
Public static function doSomething (){
Echo "Doing something \ n ";
}
}
Class HelloWorld {
Use World;
Public function getWorld (){
Return 'get world ';
}
}
$ Obj = new HelloWorld ();
$ Obj-> sayHello ();
$ Obj-> sayWorld ();
Echo $ Obj-> getWorld (). "\ n ";
HelloWorld: doSomething ();
$ Obj-> inc ();
$ Obj-> inc ();
The output result is as follows:
Hello
World
Get World
Doing something
1
2