trait的用法 解决多继承问题(不过它并不是继承,一定要清楚明白)

1 篇文章 0 订阅

首先重要的事情说三遍:

    trait不是继承,和extends不一样。
    trait不是继承,和extends不一样。
    trait不是继承,和extends不一样。

请记住这个大前提,要不然在接下来的讲解中,你会很苦恼。会不断的问自己为什么,为什么!

1.用法

      先上个实例:

<?php
trait trait1 {
    public function ceshi(){
        echo "ceshi";
    }
}
class C1{
    public function ceshi2(){
        echo "ceshi2";
    }
}
class C2 extends C1{
    use trait1;
}
$aa = new C2();
$aa->ceshi();
$aa->ceshi2();
//输出ceshiceshi2
?>

按这个实例来讲解下,不说官方语言。其实就是把一个类的东西,完全复制到你的当前类中了。(或许底层不是这样的哈,但是在使用上,我就是这么理解 的。这也有助于接下来的理解,因为他和继承是不同的。记住!)

2.特性

    优先性:

           这个顺序在官方的解释是这样的:

            

        官方是把trait中的方法和继承类也做了优先级对比。我告诉你,千万不要作对比。你会蒙圈,也因此需要多记几个东西。

你只要记住。trait的优先级没有本来的类中的方法高就可以了。如果 本来得类中有了trait中相同名字的方法按照本来的类的方法执行。至于继承的类,只要记住。那就是我继承类。因为trait属于本来的类的一部分了。所以对于继承来的类。就是普通继承的特性。

    多个:

        trait可以有多个,use a,b,c;

    抽象成员:

        trait 也是有抽象方法的哈。至于用法啥的和类的抽象方法我没发现什么区别,上一段代码简单看下吧。

        

<?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;
    }
}
$a = new MyHelloWorld();
$a->setWorld('world');
$a->sayHelloWorld();
//输出 Hello world
?>
静态方法,静态变量:

    静态方法就不说了,一样。静态变量是让我剧恶心的。上段代码自己看下!

    可能 很多人一下 就能理解,不过我当时确实没理解,写出来一是给自己提个醒。也为那么蒙在水里的提个醒

<?php
trait Counter {
    static $d = 1;
    public function inc() {
        static $c = 0;
        $c = $c + 1;
        echo "$c\n";
    }
    public function ww(){
        self::$d++;
    }
}

class C1 {
    use Counter;
}

class C2 {
    use Counter;
}

$o = new C1(); 
echo $o::$d;
$o->ww();
echo $o::$d;
$p = new C2(); 
echo $p::$d;
//输出 121
?>

对于这段代码我就在想为什么不说122。明明trait 都是counter啊。

为什么呢?因为counter已经被辅助到 c1 和  c2 里了 ,他已经变成两份了。互不干扰。

有人会说这有什么 可不明白的。很正常嘛!

那我在上一个代码

<?php
class a{
    static $rr = 1;
}
class Person extends a{
    function __construct() {
        self::$rr++;
    }
 
    static function getId() {
        return self::$rr;
    }
}
class Person1 extends a{
    function __construct() {
        self::$rr++;
    }
 
    static function getId() {
        return self::$rr;
    }
}
echo Person::$rr;   //output 0
echo Person1::$rr;
 
$p1=new Person();
echo $p1::$rr;
$p2=new Person1();
echo $p2::$rr;

//1123
?>

看到了吧,这就是我让你注意的,继承和trait 是不同的,就体现在这里。

多个不同的类继承同一个类,这个类的static 是一个。

多个不同的类use不同的trait,这个trait的static,已经被分成多个放到了每个类中。

这里要注意哈!

3.注意点

    1.相同的方法名会被覆盖,可是相同的变量名会报有问题(完全相同的变量和赋值,7.0以下警告,7.0以上不报错。不过不要尝试这个东西,别给自己找trouble,好吧!)

4.解决冲突

    1.方法冲突

        就是本类和trait的方法名相同了。

        

<?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;
    }
}
$dd = new Aliased_Talker();
$dd->bigTalk();
$dd->talk();
$dd->smallTalk();
//输出 ABb 
?>

看代码我觉得聪明的你应该可以明白

讲解下两个关键的东西:

    insteadof  前面的是要的 用签名的 替换掉 后面的

    as 别名,很简单


trait这个东西在laravel用的很多,所以今天总结了一下



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值