茄子在线看片免费人成视频,午夜福利精品a在线观看,国产高清自产拍在线观看,久久综合久久狠狠综合

    <s id="ddbnn"></s>
  • <sub id="ddbnn"><ol id="ddbnn"></ol></sub>

  • <legend id="ddbnn"></legend><s id="ddbnn"></s>

    PHP 實(shí)現(xiàn)代碼復(fù)用的一個(gè)方法 traits新特性
    來源:易賢網(wǎng) 閱讀:1160 次 日期:2015-03-13 10:01:30
    溫馨提示:易賢網(wǎng)小編為您整理了“PHP 實(shí)現(xiàn)代碼復(fù)用的一個(gè)方法 traits新特性”,方便廣大網(wǎng)友查閱!

    這篇文章主要介紹了PHP 實(shí)現(xiàn)代碼復(fù)用的一個(gè)方法,traits的新特性的相關(guān)資料,需要的朋友可以參考下

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

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

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

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

    Trait 示例

    代碼如下:

    <?php

    trait ezcReflectionReturnInfo {

    function getReturnType() { /*1*/ }

    function getReturnDescription() { /*2*/ }

    }

    class ezcReflectionMethod extends ReflectionMethod {

    use ezcReflectionReturnInfo;

    /* ... */

    }

    class ezcReflectionFunction extends ReflectionFunction {

    use ezcReflectionReturnInfo;

    /* ... */

    }

    ?>

    優(yōu)先級

    從基類繼承的成員被 trait 插入的成員所覆蓋。優(yōu)先順序是來自當(dāng)前類的成員覆蓋了 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();

    ?>

    以上例程會輸出:Hello World!

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

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

    代碼如下:

    <?php

    trait HelloWorld {

    public function sayHello() {

    echo 'Hello World!';

    }

    }

    class TheWorldIsNotEnough {

    use HelloWorld;

    public function sayHello() {

    echo 'Hello Universe!';

    }

    }

    $o = new TheWorldIsNotEnough();

    $o->sayHello();

    ?>

    以上例程會輸出:Hello Universe!

    多個(gè) trait

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

    多個(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();

    ?>

    以上例程會輸出:Hello World!

    沖突的解決

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

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

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

    沖突解決的例子

    代碼如下:

    <?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 操作符來定義了 talk 來作為 B 的 bigTalk 的別名。

    修改方法的訪問控制

    使用 as 語法還可以用來調(diào)整方法的訪問控制。

    修改方法的訪問控制的例子

    代碼如下:

    <?php

    trait HelloWorld {

    public function sayHello() {

    echo 'Hello World!';

    }

    }

    // 修改 sayHello 的訪問控制

    class MyClass1 {

    use HelloWorld { sayHello as protected; }

    }

    // 給方法一個(gè)改變了訪問控制的別名

    // 原版 sayHello 的訪問控制則沒有發(fā)生變化

    class MyClass2 {

    use HelloWorld { sayHello as private myPrivateHello; }

    }

    ?>

    從 trait 來組成 trait

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

    從 trait 來組成 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();

    ?>

    以上例程會輸出:Hello World!

    Trait 的抽象成員

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

    表示通過抽象方法來進(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 "$c\n";

    }

    }

    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è)屬性,那類將不能定義同樣名稱的屬性,否則會產(chǎn)生一個(gè)錯(cuò)誤。如果該屬性在類中的定義與在 trait 中的定義兼容(同樣的可見性和初始值)則錯(cuò)誤的級別是 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 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

    }

    ?>

    第一個(gè)use是用于 namespace 的 use Foo\Test,找到的是 \Foo\Test,第二個(gè) use 是使用一個(gè)trait,找到的是\Foo\Bar\Foo\Test。

    __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的方法可以被定義為在普通類的靜態(tài)方法,就可以被調(diào)用

    實(shí)例如下

    代碼如下:

    <?php

    trait Foo {

    function bar() {

    return 'baz';

    }

    }

    echo Foo::bar(),"\\n";

    ?>

    小伙伴們對于traits的新特性是否熟悉了呢,希望本文能對大家有所幫助。

    更多信息請查看IT技術(shù)專欄

    更多信息請查看網(wǎng)絡(luò)編程
    由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

    2026上岸·考公考編培訓(xùn)報(bào)班

    • 報(bào)班類型
    • 姓名
    • 手機(jī)號
    • 驗(yàn)證碼
    關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機(jī)站點(diǎn) | 投訴建議
    工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
    云南網(wǎng)警備案專用圖標(biāo)
    聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
    咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
    云南網(wǎng)警報(bào)警專用圖標(biāo)