Traits is a new method added in 5.4 to achieve code reuse.
php is a single inheritance language. We cannot extend multiple base classes in one class to achieve code reuse like Java. Now Traits can solve this code reuse problem. It allows developers to use multiple base classes in different classes. Implement code reuse in classes.
Traits and classes are semantically defined to reduce the complexity of the code and avoid the problem of multiple inheritance.
Traits are similar to classes, but are only used to provide a set of functions in a unified and fine-grained manner. They cannot be instantiated inside Traits, that is, there is no class-like constructor __construct(). Traits acts as an extension of PHP's traditional inheritance and implements horizontal integration; therefore, inheritance is no longer needed in application classes.
1) How to use
Use the keyword 'use' to reference Traits in the class. Multiple Traits are separated by ','.
The example code is as follows:
<?php trait ezcReflectionReturnInfo { function getReturnType() { } function getReturnDescription() { } }class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } class ezcReflectionFunction extends ReflectionFunction { use ezcReflectionReturnInfo; /* ... */ } ?>
2) Priority
The member functions in the base class will be overridden by the functions in Traits, and the member functions in the current class will override the functions in Traits.
<?php class Base { public function sayHello() { echo 'Hello '; } } trait SayWorld { public function sayHello() { parent::sayHello(); echo "World!\n"; } } class MyHelloWorld extends Base { use SayWorld; } class MyHelloWorldExt extends Base { use SayWorld; public function sayHello() { /** * 这里是5.4中的新的改动,5.4之前的版本会提示: * PHP Fatal error: Cannot use string offset as an array * 5.4中改进为返回字符串中的该索引号的字符 */ $str = "Arvin"; echo $str[0][0];// echo 'A'; } public function shortArray() { $array = ['first', 2, 3, 4];//5.4中的数组简单语法 echo $array[0];//5.4中的数组解引用取数组元素方法 } } $o = new MyHelloWorld(); $o->sayHello(); $oe = new MyHelloWorldExt(); $oe->sayHello(); echo "\n"; $oe->shortArray();
Output:
Hello World! A first
3) Multiple Traits
Multiple Traits can be added to the declaration of a class, and multiple Traits are separated by ",".
<?php trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World'; } } class MyHelloWorld { use Hello, World; } $o = new MyHelloWorld(); $o->sayHello(); $o->sayWorld(); ?>
Output result:
Hello World
4) Multiple Traits Conflict
If two traits added to the same class have the same function name and are not processed explicitly, an error will be generated.
In order to resolve the conflict between two functions with the same name in Tratis in the same class, you need to use the insteadof operator to select the correct function.
Because of the uniqueness and exclusivity of methods, the 'as' operator is allowed to be used after conflicting functions to resolve internal conflicts.
<?php 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; } } ?>
In the above example, Talker uses Traits A and B, so there is a conflict between the same function names in both.
alker defines that smallTalk is taken from Traits B and bigTalk is taken from Traits A.
Aliased_Talker uses the as operator to ensure that bigTalk in Traits B is implemented through the alias talk.
5) Change function access permissions
We can use as syntax to change the access permission attributes of functions in Traits.
<?php trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } // Change visibility of sayHello,改变sayHello的访问权限。 class MyClass1 { use HelloWorld { sayHello as protected; } } // Alias method with changed visibility // sayHello visibility not changed,设置别名myPrivateHello。 class MyClass2 { use HelloWorld { sayHello as private myPrivateHello; } } ?>
6) Traits form new Traits
Just like many classes, Traits can be used in classes, and Traits can be used in Traits. One or more Traits can be defined in one Traits, and these Traits can be defined in other Traits as part or all members.
<?php 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(); ?>
The above routine will output:
Hello World!
7) Abstract Trait members
In order to enforce certain methods in a class, you can use abstract methods in Traits.
For example:
<?php trait Hello { public function sayHelloWorld() { echo 'Hello '.$this->getWorld(); } abstract public function getWorld(); } class MyHelloWorld { private $world; use Hello; public function __construct($world) { $this->world = $world; } public function getWorld() { return $this->world; } } /** * 这里用到了5.4新功能 类实例化解引用操作 * (new class())->method(); */ (new MyHelloWorld('Arvin'))->sayHelloWorld(); ?>
This example output:
Hello Arvin
8) Static Trait members
static static variables cannot be defined in Traits, but they can be defined in Tratis functions. Static functions can also be defined in Tratis.
<?php trait Counter { public function inc() { static $c = 0;//静态变量 $c += 1; echo "$c\n"; } /** * 静态方法 */ public static function doSomething() { echo 'Doing something'; } } class C1 { use Counter; } (new C1())->inc(); // echo 1 C1::doSomething(); ?> 输出为: 1 Doing something
9) Traits define attributes
If an attribute is defined in a trait, an attribute with the same name cannot be defined in the class that references the trait. If the attribute defined in the class has the same attribute as the attribute defined in the trait Same name and access visibility, an E_STRICT hint, otherwise a syntax error is thrown.
<?php trait PropertiesTrait { public $x = 1; public $y = 2; } class PropertiesExample { use PropertiesTrait; public $x = 1; //public $y = 3; } $example = new PropertiesExample; echo $example->x, $example->y; ?>
Output:
12
Post some of the new features of php5.4.0 changelog at the end:
Added short array syntax support ([1,2,3]), see UPGRADING guide for full details. Added binary numbers format (0b001010). Added support for Class::{expr}() syntax. Added support for Traits.//本文的主要内容 Added closure $this support back. Added array dereferencing support.//数组解引用支持,上文中有实例 Added callable typehint. Added indirect method call through array. #47160. Added DTrace support.//传说DTrace是一个性能分析工具,可以跟踪出函数调用点,返回点等数据 Added class member access on instantiation (e.g. (new foo)->bar()) support.//类新实例解引用操作,上文中有实例
This article is intended to attract others, and I hope everyone will continue to explore the new features of php5.4. ^_^