Since PHP 5.4.0, PHP has implemented a code reuse method called trait.
Trait 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 method in separate classes within different hierarchies.
Trait is a solution for PHP multiple inheritance. For example, it would be cumbersome to inherit two Abstract classes at the same time, Trait to solve the problem.
It adds a combination of horizontal features to traditional inheritance.
Example 1: Defining trait with the trait keyword
Trait first_trait{public function Hello () { return ' hello '; }}
Example 2: Using Trait in class, using the Use keyword, separated by commas when using multiple trait
Trait first_trait{public function Hello () { return ' hello '; }} Trait second_trait{public function World () { return ' world '; }} Class first_class{use first_trait,second_trait;} $obj =new First_class (); Echo $obj->hello (); Echo $obj->world ();
Example 3: Priority
Members that inherit from the base class are overwritten by the members that are inserted by trait. Precedence is the method from which the member of the current class overrides the trait, and trait overrides the inherited method.
Example: A member inherited from a base class is overwritten by a member inserted by trait
Class Base {public function SayHello () { echo ' Hello '; }} Trait Sayworld {public function SayHello () { Parent::sayhello (); Echo ' world! '; }} Class Myhelloworld extends Base {use Sayworld;} $o = new Myhelloworld (); $o->sayhello ();//result of output Hello world!
Example: the member of the current class overrides the Trait method
Trait HelloWorld {public function SayHello () { echo ' Hello world! '; }} Class Theworldisnotenough {use HelloWorld; Public Function SayHello () { echo ' Hello universe! '; }} $o = new Theworldisnotenough (); $o->sayhello ();//result of output Hello universe!
Example of nesting between 4:trait
Trait first_trait{public function Hello () { echo ' hello '; }} Trait second_trait{ //trait between the nested use first_trait; Public Function World () { echo ' world '; }} Class first_class{use second_trait;} $obj =new First_class (); Echo $obj->hello (); Echo $obj->world ();
Example 5: You can declare an abstract method in trait, use its class or trait to implement an abstract method
Trait first_trait{public function Hello () { echo ' hello '; } Abstract method public abstract function test ();} Trait second_trait{ //trait between the nested use first_trait; Public Function World () { echo ' world '; } Implement the test method in first_trait public function test () { echo '! '; }} Class first_class{use second_trait;} $obj =new First_class (); Echo $obj->hello (); Echo $obj->world (); Echo $obj->test ();//Output helloworld!
Example 6: conflict resolution
If two trait all insert a method with the same name, a fatal error will occur if the conflict is not resolved explicitly.
In order to resolve the naming conflicts of multiple trait in the same class, it is necessary to use the insteadof operator to explicitly specify which of the conflicting methods to use.
The above method only allows other methods to be excluded, as operator can introduce one of the conflicting methods to another name, equivalent to the alias of the method.
Trait A {public function SmallTalk () { echo ' A '; } Public Function Bigtalk () { echo ' A '; }} Trait B {public function SmallTalk () { echo ' B '; } Public Function Bigtalk () { echo ' B '; }} Class Talker {Use A, b { b::smalltalk insteadof A;//trait B's SmallTalk method will replace the trait method of SmallTalk A A::bigta LK Insteadof B; The Bigtalk method of trait a replaces the Bigtalk method of trait B }}class aliased_talker {use A, b { b::smalltalk insteadof a;//t The Smalltalk method of the Rait B replaces the Smalltalk method of trait a A::bigtalk insteadof method of A is a b;//trait method instead of Bigtalk b : : Bigtalk as Talk; Use the AS operator to define the talk method as the alias of the Bigtalk method of B }} $obj =new Talker (), $obj->smalltalk (), $obj->bigtalk ();//Results Output BA $obj 2=new Aliased_talker (); $obj 2->talk ();//outputs B
Example 7: Modify access control for a method
Trait HelloWorld {public function SayHello () { echo ' Hello world! '; }} Modify SayHello access Control class MyClass1 {use HelloWorld {SayHello as protected;}} Give method a changed access control alias//original SayHello access control is not changed class MyClass2 {use HelloWorld {SayHello as Private Myprivatehello;}}
Example 8:trait can also define attributes
Trait propertiestrait {public $x = 1;} Class Propertiesexample {use propertiestrait;} $example = new Propertiesexample; $example->x;
If trait defines an attribute, the class will not be able to define a property of the same name, or an error will result. If the attribute's definition in the class is compatible with the definition in trait (the same visibility and initial value) then the error level is E_STRICT
, otherwise it is a fatal error.
Trait propertiestrait {public $same = true; Public $different = false;} Class Propertiesexample {use propertiestrait; Public $same = true; Strict Standards Public $different = true;//Fatal error}
PHP implements a method of code reuse, called trait