Home  >  Article  >  Backend Development  >  Learning PHP--Traits New Features_PHP Tutorial

Learning PHP--Traits New Features_PHP Tutorial

WBOY
WBOYOriginal
2016-07-13 10:11:38839browse

Learning PHP--New Traits

Since PHP 5.4.0, PHP implements a method of code reuse called traits.
Traits is a code reuse mechanism for single-inheritance languages ​​like PHP. Traits are designed to reduce the constraints of single-inheritance languages ​​and allow developers to freely reuse method sets in independent classes within different hierarchies. The semantics of traits and class composition define a way to reduce complexity and avoid the typical problems associated with traditional multiple inheritance and mixins.
Trait is similar to a class, but is only designed to combine functionality in a fine-grained and consistent way. Trait cannot be instantiated by itself. It adds a combination of horizontal features to traditional inheritance; that is, members of application classes do not need to be inherited.
Trait example
trait ezcReflectionReturnInfo {
function getReturnType() { /*1*/ }
function getReturnDescription() { /*2*/ }
}
class ezcReflectionMethod extends ReflectionMethod {
use ezcReflectionReturnInfo;
/* ... */
}
class ezcReflectionFunction extends ReflectionFunction {
use ezcReflectionReturnInfo;
/* ... */
}
?>
Priority
Members inherited from the base class are overridden by members inserted by the trait. The order of precedence is that members from the current class override the trait's methods, and the trait overrides the inherited methods.
Example of priority
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!
Members inherited from the base class are overridden by the sayHello method in the inserted SayWorld Trait. Its behavior is consistent with the methods defined in the MyHelloWorld class. The order of precedence is that methods in the current class override trait methods, which in turn override methods in the base class.
Another example of 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();
?>
The above routine will output: Hello Universe!
Multiple traits
Separated by commas, list multiple traits in the use statement, which can all be inserted into a class.
Examples of usage of multiple traits
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 two traits insert a method with the same name, a fatal error will occur if the conflict is not explicitly resolved.
In order to resolve the naming conflict of multiple traits in the same class, you need to use the insteadof operator to explicitly specify which of the conflicting methods to use.
The above method only allows to exclude other methods. The as operator can introduce one of the conflicting methods under another name.
Examples of conflict resolution
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 instead of A;
A::bigTalk instead of B;
}
}
class Aliased_Talker {
use A, B {
B::smallTalk instead of A;
A::bigTalk instead of B;
B::bigTalk as talk;
}
}
?>
In this example Talker uses traits A and B. Since A and B have conflicting methods, they define using smallTalk from trait B and bigTalk from trait A.
Aliased_Talker uses the as operator to define talk as an alias of B's ​​bigTalk.
Modify method access control
Using as syntax can also be used to adjust the access control of methods.
Example of modifying method access control
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 access control
//The access control of the original sayHello has not changed
class MyClass2 {
use HelloWorld { sayHello as private myPrivateHello; }
}
?>
Compose trait from trait
Just as classes can use traits, other traits can also use traits. By using one or more traits when a trait is defined, it can combine some or all members of other traits.
Examples of composing traits from traits
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
In order to enforce requirements on the classes used, traits support the use of abstract methods.
Indicates an example of enforcing requirements through abstract methods
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 Trait
Traits can be defined by static members and static methods.
Example of static variable
trait Counter {
public function inc() {
static $c = 0;
$c = $c + 1;
echo "$cn";
}
}
class C1 {
use Counter;
}
class C2 {
use Counter;
}
$o = new C1(); $o->inc(); // echo 1
$p = new C2(); $p->inc(); // echo 1
?>
Example of static method
trait StaticExample {
public static function doSomething() {
return 'Doing something';
}
}
class Example {
use StaticExample;
}
Example::doSomething();
?>
Examples of static variables and static methods
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
?>
Properties
Trait can also define properties.
Example of defining attributes
trait PropertiesTrait {
public $x = 1;
}
class PropertiesExample {
use PropertiesTrait;
}
$example = new PropertiesExample;
$example->x;
?>
If the trait defines a property, the class cannot define a property with the same name, otherwise an error will be generated. If the property's definition in the class is compatible with its definition in the trait (same visibility and initial value) then the error level is E_STRICT, otherwise it is a fatal error.
Examples of conflicts
trait PropertiesTrait {
public $same = true;
public $different = false;
}
class PropertiesExample {
use PropertiesTrait;
public $same = true; // Strict Standards
public $different = true; // Fatal error
}
?>
Differences in Use
Examples of different uses
namespace FooBar;
use FooTest; // means FooTest - the initial is optional
?>
namespace FooBar;
class SomeClass {
use FooTest; // means FooBarFooTest
}
?>
The first use is use FooTest for namespace, and FooTest is found. The second use is to use a trait, and FooBarFooTest is found.
__CLASS__ and __TRAIT__
__CLASS__ returns the class name of the use trait, __TRAIT__ returns the trait name
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
 
 
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;
 
调用trait方法
虽然不很明显,但是如果Trait的方法可以被定义为在普通类的静态方法,就可以被调用
 
实例如下
 
trait Foo { 
    function bar() { 
        return 'baz'; 
    } 
 
echo Foo::bar(),"\n"; 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/927607.htmlTechArticlePHP的学习--Traits新特性 自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。 Traits 是一种为类似 PHP 的单继承语言而准备的代码复用...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn