久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      PHP實(shí)現(xiàn)代碼復(fù)用的traits新特性的方法

      PHP實(shí)現(xiàn)代碼復(fù)用的traits新特性的方法

      在閱讀yii2源碼的時(shí)候接觸到了trait,就學(xué)習(xí)了一下,寫(xiě)下博客記錄一下。

      自 PHP 5.4.0 起,PHP 實(shí)現(xiàn)了代碼復(fù)用的一個(gè)方法,稱(chēng)為 traits。

      Traits 是一種為類(lèi)似 PHP 的單繼承語(yǔ)言而準(zhǔn)備的代碼復(fù)用機(jī)制。Trait 為了減少單繼承語(yǔ)言的限制,使開(kāi)發(fā)人員能夠自由地在不同層次結(jié)構(gòu)內(nèi)獨(dú)立的類(lèi)中復(fù)用方法集。Traits 和類(lèi)組合的語(yǔ)義是定義了一種方式來(lái)減少?gòu)?fù)雜性,避免傳統(tǒng)多繼承和混入類(lèi)(Mixin)相關(guān)的典型問(wèn)題。

      Trait 和一個(gè)類(lèi)相似,但僅僅旨在用細(xì)粒度和一致的方式來(lái)組合功能。Trait 不能通過(guò)它自身來(lái)實(shí)例化。它為傳統(tǒng)繼承增加了水平特性的組合;也就是說(shuō),應(yīng)用類(lèi)的成員不需要繼承。

      Trait 示例

      代碼如下:

      <?php trait ezcReflectionReturnInfo {     function getReturnType() { /*1*/ }     function getReturnDescription() { /*2*/ } } class ezcReflectionMethod extends ReflectionMethod {     use ezcReflectionReturnInfo;     /* ... */ } class ezcReflectionFunction extends ReflectionFunction {     use ezcReflectionReturnInfo;     /* ... */ } ?>

      優(yōu)先級(jí)

      從基類(lèi)繼承的成員被 trait 插入的成員所覆蓋。優(yōu)先順序是來(lái)自當(dāng)前類(lèi)的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的方法。

      優(yōu)先順序示例

      代碼如下:

      <?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(); ?>

      以上例程會(huì)輸出:Hello World!

      從基類(lèi)繼承的成員被插入的 SayWorld Trait 中的 sayHello 方法所覆蓋。其行為 MyHelloWorld 類(lèi)中定義的方法一致。優(yōu)先順序是當(dāng)前類(lèi)中的方法會(huì)覆蓋 trait 方法,而 trait 方法又覆蓋了基類(lèi)中的方法。

      另一個(gè)優(yōu)先級(jí)順序的例子

      代碼如下:

      <?php trait HelloWorld {     public function sayHello() {         echo 'Hello World!';     } } class TheWorldIsNotEnough {     use HelloWorld;     public function sayHello() {         echo 'Hello Universe!';     } } $o = new TheWorldIsNotEnough(); $o->sayHello(); ?>

      以上例程會(huì)輸出:Hello Universe!

      多個(gè) trait

      通過(guò)逗號(hào)分隔,在 use 聲明列出多個(gè) trait,可以都插入到一個(gè)類(lèi)中。

      多個(gè) trait 的用法的例子

      代碼如下:

      <?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(); ?>

      以上例程會(huì)輸出:Hello World!

      沖突的解決

      如果兩個(gè) trait 都插入了一個(gè)同名的方法,如果沒(méi)有明確解決沖突將會(huì)產(chǎn)生一個(gè)致命錯(cuò)誤。

      為了解決多個(gè) trait 在同一個(gè)類(lèi)中的命名沖突,需要使用 insteadof 操作符來(lái)明確指定使用沖突方法中的哪一個(gè)。

      以上方式僅允許排除掉其它方法,as 操作符可以將其中一個(gè)沖突的方法以另一個(gè)名稱(chēng)來(lái)引入。

      沖突解決的例子

      代碼如下:

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

      在本例中 Talker 使用了 trait A 和 B。由于 A 和 B 有沖突的方法,其定義了使用 trait B 中的 smallTalk 以及 trait A 中的 bigTalk。

      Aliased_Talker 使用了 as 操作符來(lái)定義了 talk 來(lái)作為 B 的 bigTalk 的別名。

      修改方法的訪(fǎng)問(wèn)控制

      使用 as 語(yǔ)法還可以用來(lái)調(diào)整方法的訪(fǎng)問(wèn)控制。

      修改方法的訪(fǎng)問(wèn)控制的例子

      代碼如下:

      <?php trait HelloWorld {     public function sayHello() {         echo 'Hello World!';     } } // 修改 sayHello 的訪(fǎng)問(wèn)控制 class MyClass1 {     use HelloWorld { sayHello as protected; } } // 給方法一個(gè)改變了訪(fǎng)問(wèn)控制的別名 // 原版 sayHello 的訪(fǎng)問(wèn)控制則沒(méi)有發(fā)生變化 class MyClass2 {     use HelloWorld { sayHello as private myPrivateHello; } } ?>

      從 trait 來(lái)組成 trait

      正如類(lèi)能夠使用 trait 一樣,其它 trait 也能夠使用 trait。在 trait 定義時(shí)通過(guò)使用一個(gè)或多個(gè) trait,它能夠組合其它 trait 中的部分或全部成員。

      從 trait 來(lái)組成 trait的例子

      代碼如下:

      <?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(); ?>

      以上例程會(huì)輸出:Hello World!

      Trait 的抽象成員

      為了對(duì)使用的類(lèi)施加強(qiáng)制要求,trait 支持抽象方法的使用。

      表示通過(guò)抽象方法來(lái)進(jìn)行強(qiáng)制要求的例子

      代碼如下:

      <?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 的靜態(tài)成員

      Traits 可以被靜態(tài)成員靜態(tài)方法定義。

      靜態(tài)變量的例子

      代碼如下:

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

      靜態(tài)方法的例子

      代碼如下:

      <?php trait StaticExample {     public static function doSomething() {         return 'Doing something';     } } class Example {     use StaticExample; } Example::doSomething(); ?>

      靜態(tài)變量和靜態(tài)方法的例子

      代碼如下:

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

      屬性
      Trait 同樣可以定義屬性。

      定義屬性的例子

      代碼如下:

      <?php trait PropertiesTrait {     public $x = 1; } class PropertiesExample {     use PropertiesTrait; } $example = new PropertiesExample; $example->x; ?>

      如果 trait 定義了一個(gè)屬性,那類(lèi)將不能定義同樣名稱(chēng)的屬性,否則會(huì)產(chǎn)生一個(gè)錯(cuò)誤。如果該屬性在類(lèi)中的定義與在 trait 中的定義兼容(同樣的可見(jiàn)性和初始值)則錯(cuò)誤的級(jí)別是 E_STRICT,否則是一個(gè)致命錯(cuò)誤。

      沖突的例子

      代碼如下:

      <?php trait PropertiesTrait {     public $same = true;     public $different = false; } class PropertiesExample {     use PropertiesTrait;     public $same = true; // Strict Standards     public $different = true; // 致命錯(cuò)誤 } ?>

      Use的不同

      不同use的例子

      代碼如下:

      <?php namespace FooBar; use FooTest;  // means FooTest - the initial  is optional ?> <?php namespace FooBar; class SomeClass {     use FooTest;   // means FooBarFooTest } ?>

      第一個(gè)use是用于 namespace 的 use FooTest,找到的是 FooTest,第二個(gè) use 是使用一個(gè)trait,找到的是FooBarFooTest

      __CLASS____TRAIT__
      __CLASS__ 返回 use trait 的 class name,__TRAIT__返回 trait name

      示例如下

      代碼如下:

      <?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單例

      實(shí)例如下

      代碼如下:

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

      調(diào)用trait方法

      雖然不很明顯,但是如果Trait的方法可以被定義為在普通類(lèi)的靜態(tài)方法,就可以被調(diào)用

      實(shí)例如下

      代碼如下:

      <?php  trait Foo {      function bar() {          return 'baz';      }  }  echo Foo::bar(),"\n";  ?>

      相關(guān)學(xué)習(xí)推薦:PHP編程從入門(mén)到精通

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)