When it comes to PHP code reuse, we may think of inheritance the first time, but once the single-inheritance language derives too many subclasses, it creates a series of problems, such as dependency on the parent class, too much coupling, and the encapsulation of the class. So is there a better way to implement code reuse?
Since PHP 5.4.0, PHP has implemented another method of code reuse, called traits.
Traits is a code reuse mechanism that is prepared for PHP-like single-inheritance languages. Trait to reduce the limitations of single-inheritance languages, developers are free to reuse the set of methods in separate classes within different hierarchies. The semantics of Traits and class combinations are defined as a way to reduce complexity and avoid typical problems associated with traditional multi-inheritance and mixed-Class (Mixin).
Basic Use Method
Traits is very simple to use, just use the Using keyword in the class.
Trait A {public function test () { echo ' trait a::test () '; }} Class B {use A;} $b =new B (); $b->test ();
Priority level
In simple terms, the Trait priority is greater than the parent class method, but less than the current class method.
Trait A {public function test () { echo ' trait a::test () '; } Public Function test1 () { echo ' trait a::test1 () '; } } Class base{public function test () { echo ' base::test () '; } Public Function test1 () { echo ' base::test1 () '; } } Class B extends base{use A; Public Function test () { echo ' b::test () '; }} $b =new B (); $b->test ();//b::test () $b->test1 ();//trait A::test1 ()
Trait conflict issues
When using multiple Trait, a conflict occurs if the same method name exists. Use Insteadof and as to resolve method name conflict issues
Insteadof can declare a specific method that uses two of the same method name.
Trait A {public function test () { echo ' trait a::test () '; }} Trait B {public function test () { echo ' trait b::test () '; }} Class c{use a,b{ a::test insteadof b;//using Insteadof explicitly which method B::test as testb;//use as to modify another method name, you must use the Inste Adof resolve conflict Use }} $c =new C (); $c->test ();//trait a::test () $c->testb ();//trait b::test ()
Method Access Control
With the AS keyword we can modify the access rights of the Trait method
Trait A {public function test () { echo ' trait a::test () '; } Private Function Test1 () { echo ' trait a::test1 () '; }} Class b{use a{ test as protected; Test1 as public test2;//can also modify the name when changing permissions } $b =new B (); $b->test ();//fatal Error:call to protected Method B::test () $ B->test2 ();//trait A::test1 ()
Trait nested use
Trait A {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
Variables, properties, method definitions
Trait can define properties, but the same name property cannot be defined in a class
Trait A {public $test 1; } Class B {use A; public $test; Public $test 1;//strict Standards:b and A define the same ($test 1) in the composition of B ... }
Trait supports abstract methods, supports static methods, and cannot directly define static variables, but static variables can be referenced by trait methods.
Trait A {public function test1 () { static $a = 0; $a + +; echo $a; } Abstract public Function test2 (); Can define abstract method } class B {use A; Public Function Test2 () { } } $b = new B (); $b->test1 (); 1 $b->test1 ();//2
Compare JavaScript
This trait use method is somewhat similar to the call in JavaScript, which is to attach a different object to the execution environment of the current object. Of course JavaScript is a prototype-based language. There is no comparability of the two. The only way to use it is to help understand it.
function A () { this.name= "a"; This.getname=function () { console.log (this.name); }} Function B () { this.name= "B"; A.call (this);} var B = new B (); B.getname ();//a