我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

trait被称之为php的核心特性,从最经典的php@5.4开始就增加的新特性。然而,现在都php@8的时代了,这个trait特性却依然很少有人使用。那么,phptrait究竟是怎么使用的呢?

苏南大叔:php教程,如何使用trait功能,抽象提取类的公有方法? - trait公有方法
php教程,如何使用trait功能,抽象提取类的公有方法?(图4-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:win10nginx@1.15.11php@8.2.10-nts

trait是什么

苏南大叔的理解着:trait就是抽象自class的类,把其中的公共方法的代码都提取出来,放到一个trait中。可以理解为一个全是函数(类方法)的代码片段。是对class类定义的一个补充方式。

在使用场景上,其实把定义在trait中的方法函数,定义在父类里面,效果也是一样的,而且会更加好理解一些。这可能就是trait实际的使用场景很少的原因吧。

定义并使用trait

下面的代码演示了trait的最基本的使用方式,里面出现了use关键字。这里的use不是函数,没有(),直接跟上trait的名字即可。

trait N {
    public function test() {
        echo 'trait,public,苏南大叔',PHP_EOL;
    }
}
class S {
    use N;
}
$b = new S();
$b->test();

苏南大叔:php教程,如何使用trait功能,抽象提取类的公有方法? - trait使用方式
php教程,如何使用trait功能,抽象提取类的公有方法?(图4-2)

也可以定义多个trait,使用方式基本类似。

trait N {
    public function test() {
        echo 'trait,public,苏南大叔',PHP_EOL;
    }
}
trait N2 {
    public function test2() {
        echo 'trait2,public,苏南大叔',PHP_EOL;
    }
}
class S {
    use N,N2;
}
$b = new S();
$b->test();
$b->test2();

关于trait的用法,基本上到这里就结束了。后面的都是特例了,trait自身就很罕见,后面的用法更罕见。

特例一:多个trait存在同名方法

如果引入的多个trait存在着相同名称的方法,那么就会存在着歧义代码冲突。例如:

trait N {
    public function test() {
        echo 'trait,public,苏南大叔',PHP_EOL;
    }
}
trait N2 {
    public function test() {
        echo 'trait2,public,苏南大叔',PHP_EOL;
    }
}
class S {
    use N,N2;
}
$b = new S();
$b->test();

苏南大叔:php教程,如何使用trait功能,抽象提取类的公有方法? - 同名方法trait
php教程,如何使用trait功能,抽象提取类的公有方法?(图4-3)

报错如下:

Fatal error: Trait method N2::test has not been applied as S::test, because of collision with N::test

解决方案如下:

trait N {
    public function test() {
        echo 'trait,public,苏南大叔',PHP_EOL;
    }
}
trait N2 {
    public function test() {
        echo 'trait2,public,苏南大叔',PHP_EOL;
    }
}
class S {
    use N,N2 {
        N2::test insteadof N; // 选择两个trait中的同名方法
    }
}
$b = new S();
$b->test();

苏南大叔:php教程,如何使用trait功能,抽象提取类的公有方法? - use-insteadof
php教程,如何使用trait功能,抽象提取类的公有方法?(图4-4)

关键代码:

use N,N2 {
  N2::test insteadof N; // 选择两个trait中的同名方法
}

特例二:类主体有trait中的同名方法

主体类中引入trait后,发现自身存在着和trait里面同名的方法:

trait N {
    public function test() {
        echo 'trait,public,苏南大叔',PHP_EOL;
    }
}
trait N2 {
    public function test() {
        echo 'trait2,public,苏南大叔',PHP_EOL;
    }
}
class S {
    use N,N2 {
        N2::test insteadof N; // 选择两个trait中的同名方法
    }
    public function test(){
        echo '类主体自带的同名方法',PHP_EOL;
    }
}
$b = new S();
$b->test(); // 类主体自带的同名方法

这种情况下,并不报错,相当于存在了一个方法覆盖的关系。类主体的方法覆盖trait里面的同名方法。

支持public/private/static

trait N {
    public function test() {
        echo 'trait,public,苏南大叔',PHP_EOL;
    }
    private function test2() {
        echo 'trait,private,uncle sunan',PHP_EOL;
    }
    public static function test3() {
        echo 'trait,static,sunan大叔',PHP_EOL;
    }
}
class S {
    use N;
    public function test2(){
        echo '类主体覆盖同名方法的private属性',PHP_EOL;
        $this::test3();
    }
}
$b = new S();
$b->test2();

可以看到,这个代码中,本来在trait中定义的私有方法,在类主体中,被覆盖成了公开方法。

相关文章

结束语

trait虽然不常见,但是也是作为php的核心特性而存在的。更多php的经验文章,请参考苏南大叔的博客文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php