目錄
PHP的学习--Traits新特性
首頁 後端開發 php教程 PHP的学习--Traits新特性_PHP教程

PHP的学习--Traits新特性_PHP教程

Jul 13, 2016 am 10:11 AM
特性

PHP的学习--Traits新特性

 
 
自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。
 
Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法集。Traits 和类组合的语义是定义了一种方式来减少复杂性,避免传统多继承和混入类(Mixin)相关的典型问题。
 
Trait 和一个类相似,但仅仅旨在用细粒度和一致的方式来组合功能。Trait 不能通过它自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用类的成员不需要继承。
 
Trait 示例
 
 
trait ezcReflectionReturnInfo {
    function getReturnType() { /*1*/ }
    function getReturnDescription() { /*2*/ }
}
 
class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */
}
 
class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */
}
?>
 
优先级
从基类继承的成员被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
 
优先顺序示例
 
 
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 类中定义的方法一致。优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法。
 
另一个优先级顺序的例子
 
 
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!
 
多个 trait
通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。
 
多个 trait 的用法的例子
 
 
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!
 
冲突的解决
如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
 
为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
 
以上方式仅允许排除掉其它方法,as 操作符可以将其中一个冲突的方法以另一个名称来引入。
 
冲突解决的例子
 
 
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 语法还可以用来调整方法的访问控制。
 
修改方法的访问控制的例子
 
 
trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}
 
// 修改 sayHello 的访问控制
class MyClass1 {
    use HelloWorld { sayHello as protected; }
}
 
// 给方法一个改变了访问控制的别名
// 原版 sayHello 的访问控制则没有发生变化
class MyClass2 {
    use HelloWorld { sayHello as private myPrivateHello; }
}
?>
 
从 trait 来组成 trait
正如类能够使用 trait 一样,其它 trait 也能够使用 trait。在 trait 定义时通过使用一个或多个 trait,它能够组合其它 trait 中的部分或全部成员。
 
从 trait 来组成 trait的例子
 
 
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 的抽象成员
为了对使用的类施加强制要求,trait 支持抽象方法的使用。
 
表示通过抽象方法来进行强制要求的例子
 
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 的静态成员
Traits 可以被静态成员静态方法定义。
 
静态变量的例子
 
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
?>
 
静态方法的例子
 
 
trait StaticExample {
    public static function doSomething() {
        return 'Doing something';
    }
}
 
class Example {
    use StaticExample;
}
 
Example::doSomething();
?>
 
静态变量和静态方法的例子
 
 
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 同样可以定义属性。
 
定义属性的例子
 
 
trait PropertiesTrait {
    public $x = 1;
}
 
class PropertiesExample {
    use PropertiesTrait;
}
 
$example = new PropertiesExample;
$example->x;
?>
 
如果 trait 定义了一个属性,那类将不能定义同样名称的属性,否则会产生一个错误。如果该属性在类中的定义与在 trait 中的定义兼容(同样的可见性和初始值)则错误的级别是 E_STRICT,否则是一个致命错误。
 
冲突的例子
 
 
trait PropertiesTrait {
    public $same = true;
    public $different = false;
}
 
class PropertiesExample {
    use PropertiesTrait;
    public $same = true; // Strict Standards
    public $different = true; // 致命错误
}
?>
 
Use的不同
不同use的例子
 
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
}
?>
 
第一个use是用于 namespace 的 use Foo\Test,找到的是 \Foo\Test,第二个 use 是使用一个trait,找到的是\Foo\Bar\Foo\Test。
 
__CLASS__和__TRAIT__
__CLASS__ 返回 use trait 的 class name,__TRAIT__返回 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单例
 
 
 
 
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 的单继承语言而准备的代码复用...
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

win7家庭版與win7旗艦版的差異介紹 win7家庭版與win7旗艦版的差異介紹 Jul 12, 2023 pm 08:41 PM

大家都知道win7系統有很多種版本,像是win7旗艦版、win7專業版、win7家用版等,有不少用戶在家庭版和旗艦版之間糾結,不知道選擇哪個版本比較好,所以今天小編來跟大家說說win7家庭餐與win7旗艦版的差別介紹,大家一起來看看。 1.體驗不同家庭普通版使您的日常操作變得更快、更簡單,可以更快、更方便地存取使用最頻繁的程式和文件。家庭高級版讓您享有最佳的娛樂體驗,可以輕鬆欣賞和分享您喜愛的電視節目、照片、影片和音樂。旗艦版集各版本功能大全,具備Windows7家庭高級版的所有娛樂功能與專

掌握Spring MVC的關鍵概念:了解這些重要特性 掌握Spring MVC的關鍵概念:了解這些重要特性 Dec 29, 2023 am 09:14 AM

了解SpringMVC的關鍵特性:掌握這些重要的概念,需要具體程式碼範例SpringMVC是一種基於Java的Web應用開發框架,它透過模型-視圖-控制器(MVC)的架構模式來幫助開發人員建立靈活可擴展的Web應用程式。了解和掌握SpringMVC的關鍵特性將使我們能夠更有效地開發和管理我們的網路應用程式。本文將介紹一些SpringMVC的重要概念

選擇適用的Go版本,依需求和特性 選擇適用的Go版本,依需求和特性 Jan 20, 2024 am 09:28 AM

隨著網路的快速發展,程式語言也不斷演化和更新。其中,Go語言作為一種開源的程式語言,在近年來備受關注。 Go語言的設計目標是簡單、有效率、安全且易於開發和部署。它具有高並發、快速編譯和記憶體安全等特性,讓它在Web開發、雲端運算和大數據等領域中有著廣泛的運用。然而,目前Go語言也有不同的版本可供選擇。在選擇合適的Go語言版本時,我們需要考慮需求和特性兩個面向。首

5g的三個特性是什麼 5g的三個特性是什麼 Dec 09, 2020 am 10:55 AM

5g的三個特性是:1、高速率;在實際應用中,5G網路的速率是4G網路10倍以上。 2、低時延;5G網路的時延約幾十毫秒,比人的反應速度還要快。 3.廣連結;5G網路出現,配合其他技術,將會打造一個全新的萬物互聯景象。

Golang中有類似類別的物件導向特性嗎? Golang中有類似類別的物件導向特性嗎? Mar 19, 2024 pm 02:51 PM

在Golang(Go語言)中並沒有傳統意義上的類別的概念,但它提供了一種稱為結構體的資料類型,透過結構體可以實現類似類別的物件導向特性。在本文中,我們將介紹如何使用結構體實現物件導向的特性,並提供具體的程式碼範例。結構體的定義和使用首先,讓我們來看看結構體的定義和使用方式。在Golang中,結構體可以透過type關鍵字定義,然後在需要的地方使用。結構體中可以包含屬

C++ 函式的型別和特性 C++ 函式的型別和特性 Apr 11, 2024 pm 03:30 PM

C++函式有以下型別:簡單函式、const函式、靜態函式、虛函式;特性包括:inline函式、預設參數、參考回傳、重載函式。例如,calculateArea函數使用π計算給定半徑圓的面積,並將其作為輸出傳回。

java的特性是什麼 java的特性是什麼 Aug 09, 2023 pm 03:05 PM

java的特性是:1、簡單易學;2、面向對象,使得程式碼更可重複使用和維護;3、平台無關性,能在不同的作業系統上運作;4、記憶體管理,透過自動垃圾回收機制來管理記憶體;5、強型別檢查,變數在使用前必須先聲明類型;6、安全性,可以防止未經授權的存取和惡意程式碼的執行;7、多執行緒支持,能提高程式的效能和回應能力;8、異常處理,可以避免程式崩潰;9、大量的開發庫和框架;10、開源生態系統。

掌握Golang中間件的關鍵特性與應用場景 掌握Golang中間件的關鍵特性與應用場景 Mar 20, 2024 pm 06:33 PM

Golang作為一門快速、有效率的程式語言,在Web開發領域也有廣泛的應用。其中,中間件作為一種重要的設計模式,能夠幫助開發者更好地組織、管理程式碼,提高程式碼的可重複使用性和可維護性。本文將介紹Golang中中間件的關鍵特性和應用場景,並透過具體的程式碼範例來說明其用法。一、中間件的概念及作用中間件作為一種插入式的元件,位於應用程式的請求-回應處理鏈中,用

See all articles