頻道欄目
首頁 > 程序開發 > Web開發 > php > 正文
PHP5.4以后新增的trait功能使用介紹
2018-07-19 11:23:02         來源:qq_29735775的博客  
收藏   我要投稿

trait是php5.4以后新增加的一個功能,可以將多個類中,共用的一些屬性和方法提取出來做來公共trait類,就像是裝配汽車的配件,如果你的類中要用到這些配件,就直接用use導入就可以了,相當于把trait中的代碼復制到當前類中.

因為trait不是類,所以不能有靜態成員,類常量,當然也不可能被實例化。

其實一個類中的代碼,可以分為二大部分:一是我們自己寫的代碼,暫且叫私有代碼吧,還有一部分就是公共代碼了,之前主要是由父類代碼組成,F在你的類中的公共代碼又多一個新成員:trait類代碼。

如果說:繼承可以縱向擴展一個類,那么trait就是橫向擴展一個類功能

下面以實例進行演示:
//1創建一個trait類Test1

hello1(); //訪問trait類Test1中的hello1()
echo '

'; echo $obj->name; //訪問ttrait類Test1中的$name屬性 echo '
'; echo $obj->hello2(); //訪問ttrait類Test1中的hello2()

trait可以互相嵌套,一個trait類中可以用use導入另一個trait類,理解成代碼復制就可以了.

例如本例中,在Test2中要用到Test1中的代碼,我們只要改動二個地方就可以了。

一是在Test2中用use Test1;導入Test1中的代碼,

二是在Demo1類中的,去掉對Test1的引用,只保留對Test2的引用,想想這是為什么?給大家當作一個思考題吧~

修改后的代碼如下:

//1創建一個trait類Test1

name;
}
}
//3.創建Demo1類
class Demo1
{
// use Test1, Test2;
use Test2;
}
//進行測試
$obj = new Demo1;
echo $obj->hello1(); //訪問trait類Test1中的hello1()
echo '

'; echo $obj->name; //訪問ttrait類Test1中的$name屬性 echo '


'; echo $obj->hello2(); //訪問ttrait類Test1中的hello2()

剛才說過,類中導入的公共代碼,除了trait方法集,還可以有父類,如果在子類中訪問父類中的成員,大家應該很熟悉了,現在一個類除了可以從父類繼承成員,還可以從trait類中繼承,那么有一個問題就不可避免了,如果父類和trait類中的成員命名沖突怎么辦?說人話,就是重名了怎么辦?下面我們以方法重名來演示一下處理方案。

再創建一個類Demo,做為Demo1類的父類。

//3.創建父類Demo

class Demo
{
//在父類中創建一個與Test2重名的方法hello2()
public function hello2()
{
return '父類Demo::hello2()';
}
}

代碼如下:

//1創建一個trait類Test1
trait Test1
{
public $name = 'PHP中文網'; //trait類中可以用屬性
public function hello1() //trait類中主要成員是方法
{
return 'Test1::hello1()';
}
}
//2.創建triat類Test2
trait Test2
{
use Test1;
function hello2()
{
//在Test2中訪問Test1中的屬性name,注意語法與普通類是一樣的
return 'Test2::hello2()'.$this->name;
}
}
//3.創建父類Demo
class Demo
{
public function hello2()
{
return '父類Demo::hello2()';
}
}
//4.創建Demo1類
class Demo1 extends Demo
{
// use Test1, Test2;
use Test2;
}
//進行測試
$obj = new Demo1;
echo $obj->hello1(); //訪問trait類Test1中的hello1()
echo '

'; echo $obj->name; //訪問ttrait類Test1中的$name屬性 echo '


'; echo $obj->hello2(); //訪問ttrait類Test1中的hello2()

再次訪問,會發現,結果與之前完全一樣沒有任何變化,父類Demo中的hello2方法好像隱身了,壓根不存在一樣的。事實上,父類Demo中的hello2方法當然是存在的,只是被trat類Test2中的同名方法hello2覆蓋掉了,原因就是:trait類中的同名方法,訪問優先級大于父類的同名方法。

如果我們就想訪問父類中的hello2方法,怎么辦呢?只有一個辦法,要么父類方法改名,要么Test2中的方法改名,我們把Test2中的hello2方法改成hello3,再次訪問,就可以看到父類的執行結果了。

那么,我們再進一點想一下,如果在子類也有一個hello2方法呢?那么結果會是什么樣?

我們來試一下,在Demo1類中添加如下代碼:

//4.創建Demo1類
class Demo1 extends Demo
{
// use Test1, Test2;
use Test2;
//在Demo1類中創建與Test2和父類Demo中同名的方法hello2()
public function hello2()
{
return 'Demo1::hello()';
}
}

瀏覽器再次方法,果然不出所料,子類Demo1中的hello2方法的執行結果覆蓋掉了Test2中的同名方法

現在我們總結一下在同一個類中,同名方法的優先級:子類>Trait類>父類,與就是說,誰離調用者越近,誰的優先級就越高。

下面我們再討論最后一個問題:如果trait類中方法重名了,怎么辦?如果是trait類中被所有類共享的方法集,重名的可能性是非常大的。

下面我們修改一下代碼,刪除一些用不到代碼:

//1創建一個trait類Test1
trait Test1
{
public function hello()
{
return 'Test1::hello()';
}
}
//2.創建triat類Test2
trait Test2
{
function hello()
{
return 'Test2::hello()';
}
}
//3.創建類Demo
class Demo
{
use Test1, Test2{
//用Test1中的hello()方法替代Test2中的同名方法
Test1::hello insteadof Test2;
//Test2中的hello()方法用別名訪問
Test2::hello as test2Hello;
} //這里千萬不要加分號 ;
}

//進行測試
$obj = new Demo;
echo $obj->hello(); //訪問Test1中的hello()
echo '

'; echo $obj->test2Hello();//別名訪問Test2中的hello()

點擊復制鏈接 與好友分享!回本站首頁
上一篇:PHP 身份證驗證功能代碼實現
下一篇:在php里判斷手機號的代碼教程
相關文章
圖文推薦
點擊排行

關于我們 | 聯系我們 | 廣告服務 | 投資合作 | 版權申明 | 在線幫助 | 網站地圖 | 作品發布 | Vip技術培訓 | 舉報中心

版權所有: 紅黑聯盟--致力于做實用的IT技術學習網站

加拿大28火车判定方法