PHP implementation of code reuse a method traits new features
This article mainly introduces PHP implementation of code reuse of a method, traits of the new features of the relevant information, the need for friends can refer to the following
In the reading Yii2 source of contact with the trait, learn a bit, write down the blog record.
Since PHP 5.4.0, PHP has implemented a 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).
Trait is similar to a class, but only designed to combine functionality in a fine-grained and consistent way. Trait cannot be instantiated by itself. It adds a combination of horizontal attributes to traditional inheritance, meaning that members of the application class do not need inheritance.
Trait Example
The code is as follows:
Trait Ezcreflectionreturninfo {
function Getreturntype () {/*1*/}
function Getreturndescription () {/*2*/}
}
Class Ezcreflectionmethod extends Reflectionmethod {
Use Ezcreflectionreturninfo;
/* ... */
}
Class Ezcreflectionfunction extends Reflectionfunction {
Use Ezcreflectionreturninfo;
/* ... */
}
?>
Priority level
A member inherited from a base class is overwritten by a member 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 of precedence order
The code is as follows:
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 ();
?>
The above routines will output: Hello world!
Members inherited from the base class are overwritten by the SayHello method in the inserted Sayworld Trait. Its behavior is consistent with the methods defined in the Myhelloworld class. The precedence is that methods in the current class override the Trait method, and the trait method overrides the method in the base class.
Another example of priority order
The code is as follows:
Trait HelloWorld {
Public Function SayHello () {
Echo ' Hello world! ';
}
}
Class Theworldisnotenough {
Use HelloWorld;
Public Function SayHello () {
Echo ' Hello universe! ';
}
}
$o = new Theworldisnotenough ();
$o->sayhello ();
?>
The above routines will output: Hello universe!
Multiple trait
Separated by commas, multiple trait are listed in the use declaration and can be inserted into a class.
Examples of the use of multiple trait
The code is as follows:
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 ();
?>
The above routines will output: Hello world!
Resolution of conflicts
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, and the as operator can introduce one of the conflicting methods with another name.
Examples of conflict resolution
The code is as follows:
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 this example, Talker uses trait A and B. Because A and B have conflicting methods, they define the use of smallTalk in trait B and the bigtalk in trait a.
Aliased_talker uses the as operator to define talk as an alias for the bigtalk of B.
Modify access control for a method
Using the AS syntax can also be used to adjust the access control of a method.
Example of modifying access control for a method
The code is as follows:
Trait HelloWorld {
Public Function SayHello () {
Echo ' Hello world! ';
}
}
Modify access control for SayHello
Class MyClass1 {
Use HelloWorld {SayHello as protected;}
}
Give the method an alias that changes the access control
The access control of the original SayHello has not changed
Class MyClass2 {
Use HelloWorld {SayHello as Private Myprivatehello;}
}
?>
From trait to form trait
Just as classes can use trait, other trait can also use trait. When trait is defined, it can combine some or all of the members of another trait by using one or more trait.
Examples of trait from trait
The code is as follows:
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 routines will output: Hello world!
Abstract members of the Trait
In order to impose mandatory requirements on the classes used, trait supports the use of abstract methods.
An example of an abstract method to make a mandatory request
The code is as follows:
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;
}
}
?>
Static members of the Trait
Traits can be defined by static member static methods.
Examples of static variables
The code is as follows:
Trait Counter {
Public Function Inc () {
static $c = 0;
$c = $c + 1;
echo "$c \ n";
}
}
Class C1 {
Use Counter;
}
Class C2 {
Use Counter;
}
$o = new C1 (); $o->inc (); Echo 1
$p = new C2 (); $p->inc (); Echo 1
?>
Examples of static methods
The code is as follows:
Trait Staticexample {
public static function DoSomething () {
Return ' Doing something ';
}
}
Class Example {
Use Staticexample;
}
Example::d osomething ();
?>
Examples of static variables and static methods
The code is as follows:
Trait Counter {
public static $c = 0;
public static Function Inc () {
Self:: $c = self:: $c + 1;
echo Self:: $c. "\ n";
}
}
Class C1 {
Use Counter;
}
Class C2 {
Use Counter;
}
C1::inc (); Echo 1
C2::inc (); Echo 1
?>
Property
Trait can also define attributes.
Examples of defining attributes
The code is as follows:
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), the error level is e_strict, otherwise it is a fatal error.
Examples of conflicts
The code is as follows:
Trait Propertiestrait {
Public $same = true;
Public $different = false;
}
Class Propertiesexample {
Use propertiestrait;
Public $same = true; Strict Standards
Public $different = true; Fatal error
}
?>
The use of the different
Examples of different use
The code is as follows:
namespace Foo\bar;
Use Foo\test; means \foo\test-the initial \ is optional
?>
namespace Foo\bar;
Class SomeClass {
Use Foo\test; Means \foo\bar\foo\test
}
?>
The first use is used Foo\test for namespace, the \foo\test is found, the second uses is a trait, and the \foo\bar\foo\test is found.
__class__ and __trait__
__CLASS__ returns the CLASS name,__trait__ of Use trait returns trait name
Examples such as the following
The code is as follows:
Trait Testtrait {
Public Function TestMethod () {
echo "Class:". __class__. Php_eol;
echo "Trait:". __trait__. Php_eol;
}
}
Class BaseClass {
Use testtrait;
}
Class TestClass extends BaseClass {
}
$t = new TestClass ();
$t->testmethod ();
Class:baseclass
Trait:testtrait
Trait single case
Examples are as follows
The code is as follows:
Trait Singleton {
/**
* Private construct, generally defined by using class
*/
Private Function __construct () {}
public static function getinstance () {
static $_instance = NULL;
$class = __class__;
Return $_instance?: $_instance = new $class;
}
Public Function __clone () {
Trigger_error (' cloning '. __class__. ' is not allowed. ', e_user_error);
}
Public Function __wakeup () {
Trigger_error (' unserializing '. __class__. ' is not allowed. ', e_user_error);
}
}
/**
* Example Usage
*/
class Foo {
Use singleton;
Private Function __construct () {
$this->name = ' foo ';
}
}
Class Bar {
Use singleton;
Private Function __construct () {
$this->name = ' bar ';
}
}
$foo = Foo::getinstance ();
Echo $foo->name;
$bar = Bar::getinstance ();
Echo $bar->name;
Calling the Trait method
Although not obvious, if the trait method can be defined as a static method in a normal class, it can be called
Examples are as follows
The code is as follows:
Trait Foo {
function Bar () {
return ' Baz ';
}
}
Echo Foo::bar (), "\\n";
?>
The small partners are familiar with the new features of traits, I hope this article can be helpful to everyone.
http://www.bkjia.com/PHPjc/966917.html www.bkjia.com true http://www.bkjia.com/PHPjc/966917.html techarticle PHP Implementation of code reuse a method traits new features This article mainly introduces the PHP implementation of code reuse of a method, traits the new characteristics of the relevant information, the need for friends can refer to ...