Trait
trait看上去更像是为了代码的复用而写的一个小插件,它类似于include
可以用use放在类中间,让trait里面定义的方法作为class 的一部分
本身不能直接实例化
作用域
Trait 的作用域在引用该Trait 类的内部是都可见的(public 、private 等等都可以)
可以理解为use关键字将Trait 的实现代码Copy了一份到引用该Trait 的类中
Trait中属性的优先级
01 、来自当前类的成员覆盖了 trait 的方法
02 、trait 覆盖了被继承的方法
类成员优先级为:当前类>Trait >父类
03 、trait 中不能使用const
04 、trait 中定义了属性,使用插件的类不能存在相同的属性,不能会报错
<?php
class Question
{
public function publicF ()
{
echo __METHOD__ . ' public function' . PHP_EOL;
}
protected function protectF ()
{
echo __METHOD__ . ' protected function' . PHP_EOL;
}
}
trait Log
{
public function startLog ()
{
echo __METHOD__ . ' public function' . PHP_EOL;
}
protected function endLog ()
{
echo __METHOD__ . ' protected function' . PHP_EOL;
}
}
trait Check
{
public function parameterCheck ($parameters ) {
echo __METHOD__ . ' = ' .$parameters . PHP_EOL;
}
}
class Publish extends Question
{
use Log ,Check ;
public function doPublish ($para ) {
$this ->startLog();
$this ->parameterCheck($para );
$this ->endLog();
}
}
$publish = new Publish();
$publish ->doPublish("xiaoliu" );
结果
Log::startLog public function
Check ::parameterCheck = xiaoliu
Log ::endLog protected function
Insteadof和As别名、as修改访问控制
通过逗号相隔引入多个Trait
insteadof 关键字用前者取代了后者,解决引入多个Trait
as 关键字给被取代的方法起了一个别名。
as 还可以修改方法的访问控制
01 、insteadof 、as
<?php
trait Log
{
private function parameterCheck ($parameters )
{
echo __METHOD__ . ' parameter check' . $parameters . PHP_EOL;
}
private function startLog ()
{
echo __METHOD__ . ' public function' . PHP_EOL;
}
}
trait Check
{
private function parameterCheck ($parameters )
{
echo __METHOD__ . ' parameter check' . $parameters . PHP_EOL;
}
private function startLog ()
{
echo __METHOD__ . ' public function' . PHP_EOL;
}
}
class Publish
{
use Check , Log {
Check ::parameterCheck insteadof Log ;
Log::startLog insteadof Check;
Check::startLog as csl;
}
public function doPublish ()
{
$this ->startLog();
$this ->parameterCheck('params' );
$this ->csl();
}
}
$publish = new Publish();
$publish ->doPublish();
结果
Log::startLog public function
Check ::parameterCheck parameter checkparams
Check ::startLog public function
02、修改访问权限
<?php
trait Animal {
public function eat () {
echo "This is Animal eat" ;
}
}
class Dog {
use Animal {
eat as protected ;
}
}
class Cat {
use Animal {
Animal ::eat as private eaten ;
}
}
$dog = new Dog();
$dog ->eat();
$cat = new Cat();
$cat ->eat();
$cat ->eaten();
?>
tips
在引用Trait时,使用了use 关键字,use 关键字也用来引用命名空间
两者的区别在于,引用Trait时是在class 内部使用的
trait 不能实现接口
Trait也可以互相组合,还可以使用抽象方法,静态属性,静态方法等
<?php
trait Cat{
public function eat () {
echo "This is Cat eat" ;
}
}
trait Dog{
use Cat ;
public function drive () {
echo "This is Dog drive" ;
}
abstract public function getName () ;
public function test () {
static $num =0 ;
$num ++;
echo $num ;
}
public static function say () {
echo "This is Dog say" ;
}
}
class animal {
use Dog ;
public function getName () {
echo "This is animal name" ;
}
}
$animal = new animal();
$animal ->getName();
echo "<br/>" ;
$animal ->eat();
echo "<br/>" ;
$animal ->drive();
echo "<br/>" ;
$animal ::say();
echo "<br/>" ;
$animal ->test();
echo "<br/>" ;
$animal ->test();
?>
结果
This is animal name
This is Cat eat
This is Dog drive
This is Dog say
1
2