Traits is a code reuse mechanism prepared for a single inheritance language similar to PHP. Trait allows developers to freely reuse method sets in independent classes in different hierarchies to reduce the restrictions of a single inheritance language. The semantics of Traits and class combination defines a way to reduce complexity and avoid typical problems related to traditional multi-inheritance and mixed classes (Mixin. Since PHP 5.4.0, PHP has implemented a method for code reuse, called traits.
Traits is a code reuse mechanism prepared for a single inheritance language similar to PHP. Trait allows developers to freely reuse method sets in independent classes in different hierarchies to reduce the restrictions of a single inheritance language. The semantics of Traits and class combination defines a way to reduce complexity and avoid typical problems related to traditional multi-inheritance and mixed classes (Mixin.
Traits is similar to a class, but only intended to combine functions in a fine-grained and consistent manner. Trait cannot be instantiated by itself. It adds a combination of horizontal features for traditional inheritance; that is, members of the application class do not need to inherit.
Example #1 Trait Example
trait ezcReflectionReturnInfo{ function getReturnType(){} function getReturnDescription(){}}class ezcReflectionMethod extends ReflectionMethod{ use ezcReflectionReturnInfo;}class ezcReflectionFunction extends ReflectionFunction{ use ezcReflectionReturnInfo;}
Priority
The member inherited from the base class is overwritten by the member inserted by trait. The priority is that the members of the current class overwrite the trait method, while the trait method overwrites the inherited method.
Example #2 Example of priority
The member inherited from the base class is overwritten by the MyHelloWorld method in the inserted SayWorld Trait. Its behavior is the same as that defined in the MyHelloWorld class. The priority is that the methods in the current class will overwrite the trait method, and the trait method overwrites the methods in the base class:
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();
Output result:
Hello World!
Example #3 Example of another priority order
trait HelloWorld{ public function sayHello(){ echo 'Hello World!'; }}class TheWorldIsNotEnough{ use HelloWorld; public function sayHello(){ echo 'Hello Universe!'; }}$o = new TheWorldIsNotEnough;$o -> sayHello();
Output result:
Hello Universe!
Multiple trait
Separated by commas (,). Multiple trait entries are listed in the use declaration and can be inserted into a class.
Example #4 usage of multiple trait
trait Hello{ public function sayHello(){ echo 'Hello '; }}trait World{ public function sayWorld(){ echo 'World'; }}class MyHelloWorld{ use Hello,World; public function sayExclamationMark(){ echo '!'; }}$o = new MyHelloWorld();$o -> sayHello();$o -> sayWorld();$o -> sayExclamationMark();
Output result:
Hello World!
Conflict resolution
If both trait inserts a method with the same name, a fatal error will occur if the conflict is not explicitly resolved.
To resolve naming conflicts between multiple trait classes, you must use the insteadof operator to specify which of the conflicting methods to use.
The preceding method can only exclude other methods. the as operator can introduce one conflicting method with another name.
Example #5 conflict resolution
In this example, Talker uses trait A and B. Because A conflicts with B, it defines the use of smallTalk in trait B and bigTalk in trait.
Aliased_Talker uses the as operator to define talk as the alias of B's bigTalk.
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; A::bigTalk insteadof B; }}class Aliased_Talker{ use A,B{ B::smallTalk insteadof A; A::bigTalk insteadof B; B::bigTalk as talk; }}$t = new Talker;$t->smallTalk(); //b$t->bigTalk(); //A$at = new Aliased_Talker;$at->smallTalk(); //b$at->bigTalk(); //A$at->talk(); //B
Access control for modification methods
The as syntax can also be used to adjust the access control of methods.
Example #6 modify method access control
Trait HelloWorld {public function sayHello () {echo 'Hello World! ';}} // Modify sayHello's access control class MyClass1 {use HelloWorld {sayHello as protected ;}} // give the method an access control alias that has changed the access control // the access control of the original sayHello does not change class MyClass2 {use HelloWorld {sayHello as private myPrivateHello ;}}
From trait to trait
Just as the class can use trait, other trait can also use trait. When trait is defined, one or more trait can be used to combine some or all members of other trait.
Example #7 trait
trait Hello{ public function sayHello(){ echo 'Hello '; }}trait World{ public function sayWorld(){ echo 'World!'; }}trait HelloWorld{ use Hello,World;}class MyHelloWorld{ use HelloWorld;}$o = new MyHelloWorld;$o -> sayHello();$o -> sayWorld();
Output result:
Hello World!
Abstract member of Trait
To enforce requirements on the classes used, trait supports the use of abstract methods.
Example #8 indicates that the abstract method is used to enforce the requirements.
trait Hello{ public function sayHelloWorld(){ echo 'Hello'.$this->getWorld(); } abstract public function getWorld();}class MyHelloWorld{ private $world; use Hello; public function getWorld(){ return $this->world; } public function setWorld($val){ $this->world = $val; }}
Trait static member
Static variables can be referenced by the trait method, but cannot be defined by trait. However, trait can define static methods for the classes used.
Example #9 static variables
trait Counter{ public function inc(){ static $c = 0; $c = $c + 1; echo "{$c}
"; }}class C1{ use Counter;}class C2{ use Counter;}$o = new C1();$o->inc(); //echo 1$p = new C2;$p->inc(); //echo 1
Example #10 static method
trait StaticExample{ public static function doSomething(){ return 'Doing something.'; }}class Example{ use StaticExample;}Example::doSomething();
Output result: Doing something.
Attribute
Trait can also define attributes.
Example #11 define attributes
trait PropertiesTrait{ public $x = 1;}class PropertiesExample{ use PropertiesTrait;}$example = new PropertiesExample;$example->x;
If trait defines an attribute, the class cannot define the attribute with the same name. Otherwise, an error occurs. If the definition of this attribute in the class is compatible with the definition in trait (the same visibility and initial value), the error level is E_STRICT, otherwise it is a fatal error.
Example #12 conflict
Trait PropertiesTrait {public $ sname = true; public $ different = false;} class PropertiesExample {use PropertiesTrait; public $ sname = true; // Strict Standards public $ different = true; // fatal error}