A new feature of traits in PHP code reuse

Source: Internet
Author: User
Tags traits
This article mainly introduces a method for PHP code reuse. For more information about the new features of traits, refer to trait when reading the source code of yii2, after learning, write down the blog record.

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.

Trait is similar to a class, but it is 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.

Trait example

The code is as follows:


<? Php
Trait ezcReflectionReturnInfo {
Function getReturnType () {/* 1 */}
Function getReturnDescription () {/* 2 */}
}
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.

Priority example

The code is as follows:


<? Php
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 routine will output: Hello World!

The member inherited from the base class is overwritten by the sayHello 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.

Example of another priority order

The code is as follows:


<? Php
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 routine will output: Hello Universe!

Multiple trait

Separated by commas (,). Multiple trait entries are listed in the use declaration and can be inserted into a class.

Examples of multiple trait usage

The code is as follows:


<? Php
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 routine will output: 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 of conflict resolution

The code is as follows:


<? Php
Trait {
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: bigTalk insteadof B;
}
}
Class Aliased_Talker {
Use A, B {
B: smallTalk insteadof;
A: bigTalk insteadof B;
B: bigTalk as talk;
}
}
?>

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.

Access control for modification methods

The as syntax can also be used to adjust the access control of methods.

Example of modifying method access control

The code is as follows:


<? Php
Trait HelloWorld {
Public function sayHello (){
Echo 'Hello World! ';
}
}
// Modify the access control of 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 version is not changed.
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 of trait composition from trait

The code is as follows:


<? 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!

Abstract member of Trait

To enforce requirements on the classes used, trait supports the use of abstract methods.

An example of a forcible requirement using an abstract method

The code is as follows:


<? Php
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

Traits can be defined by static methods of static members.

Static variable example

The code is as follows:


<? Php
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
?>

Static method example

The code is as follows:


<? Php
Trait StaticExample {
Public static function doSomething (){
Return 'doing something ';
}
}
Class Example {
Use StaticExample;
}
Example: doSomething ();
?>

Static variables and static methods

The code is as follows:


<? Php
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
?>

Attribute
Trait can also define attributes.

Example of defining attributes

The code is as follows:


<? Php
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.

Conflicting examples

The code is as follows:


<? Php
Trait PropertiesTrait {
Public $ same = true;
Public $ different = false;
}
Class PropertiesExample {
Use PropertiesTrait;
Public $ same = true; // Strict Standards
Public $ different = true; // fatal error
}
?>

Different Use

Examples of different use

The code is as follows:


<? Php
Namespace Foo \ Bar;
Use Foo \ Test; // means \ Foo \ Test-the initial \ is optional
?>
<? Php
Namespace Foo \ Bar;
Class SomeClass {
Use Foo \ Test; // means \ Foo \ Bar \ Foo \ Test
}
?>

The first use is the use Foo \ Test for namespace, and \ Foo \ Test is found. The second use is a trait and \ Foo \ Bar \ Foo \ Test is found.

_ CLASS _ and _ TRAIT __
_ CLASS _ returned use trait class name ,__ TRAIT _ returned trait name

Example:

The code is as follows:


<? Php
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 Singleton

The instance is as follows:

The code is as follows:


<? Php
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;

Call the trait method

Although not obvious, if the Trait method can be defined as a static method in a common class, it can be called.

The instance is as follows:

The code is as follows:


<? Php
Trait Foo {
Function bar (){
Return 'Baz ';
}
}
Echo Foo: bar (), "\ n ";
?>

Are you familiar with the new features of traits? I hope this article will help you.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.