trait特性,什么是trait,整理版

作为PHP5.4引入新特性trait,有不少读者感觉比较陌生。

本篇从背景作用使用三个方面分析trait,力求以最通俗的语言解释清楚。

背景

PHP在面向对象的设计时, 被设计为单继承. 什么叫单继承, 一个类A只能继承一个类B, 再由B类继承C类. 而不能A类同时继承B类和C类.

正确的写法:demo1.php

<?php

class C{}

class B extends C{}

class A extends B{}

$obj = new A;

var_dump($obj);

会得到一个对象

/home/vagrant/Code/blog/demo1.php:11:
object(A)[1]

//注意

//A类同时继承B类和C类, 这样写是不允许的

例如:

<?php

class C{}
class B{}

class A extends B,C{}

$obj = new A;

var_dump($obj);


//代码是错误的。
( ! ) Parse error: syntax error, unexpected token ",", expecting "{" in /home/vagrant/Code/blog/demo2.php on line 6

说人话, 就是一个儿子只能有一个父亲, 但是反过来呢?一个父亲是可以有多个儿子的.

如果想A类既使用B的方法又使用C的方法, PHP提出了接口(Interface). PHP虽然是单继承, 但是可以多实现. 什么叫多实现, 一个类A可以同时实现B接口和C接口.(demo3.php)

<?php

interface C{}

interface B{}

class A implements B,C{}

//A类同时实现接口B和接口C, 这样是允许的


$obj = new A;

var_dump($obj);

同样会得到一个对象

/home/vagrant/Code/blog/demo3.php:11:
object(A)[1]

作用

关键词: 假多继承, 代码复用, 类的包含

现在有这样一个场景

需求: A类既可以使用B类的方法又可以使用C的方法, A类和B类是继承关系, 但是B和C没有继承关系, 怎么解决?

方法:A类继承B类, 同时实现C接口(demo4.php)

<?php

interface C{
    public function ccc();
}

class B{
    public function bbb()
    {
        echo "我是B类的bbb方法<br>";
    }
}

class A extends B implements C{
    public function ccc()
    {
        echo "我是A类,我要实现接口C定义的方法<br>";
    }
}

$obj = new A;
$obj ->ccc();
$obj ->bbb();
~
~

强烈建议上面的代码,敲10遍以上。

(拓展: 接口)

接口不能被实例化

接口是为了规范显现它的子类,以达到统一的目的

接口中只有:常量和抽象方法

接口里的所有方法都是抽象方法,不能写方法体,并且,接口的抽象方法不需要写abstract。

子类继承接口的方法,叫 实现,所以说接口是用来实现的(涉及php基础知识)

如果这个时候有一个D类, 也要继承B类, 实现C接口, 需要重复的写这段代码(demo5.php)

<?php

interface C{
    public function ccc();
}

class B{
    public function bbb()
    {
        echo "我是B类的bbb方法<br>";
    }
}

class A extends B implements C{
    public function ccc()
    {
        echo "我是A类,我要实现接口C定义的方法<br>";
    }
}

class D extends B implements C{
    //这段代码是重复的
    public function ccc()
    {
        echo "我是D类,我要实现接口C定义的方法<br>";
    }
}
$obj = new A;
$obj ->ccc();
$obj ->bbb();

使用

思考: 能不能将这部分重复的代码定义在一个类中, A类和D类包含这个类呢?

这个时候trait应用而生(demo6.php)

<?php

interface C{
    public function ccc();
}

class B{
    public function bbb()
    {
        echo "我是B类的bbb方法<br>";
    }
}

trait E{
    public function ccc()
    {
        echo "我是trait,我实现了ccc方法<br>";
//      echo "我是trait,我是".__CLASS__."类,我实现了ccc方法<br>";
    }
}

class A extends B implements C{
    use E;
}

class D extends B implements C{
    use E;
}


$obj = new A;
$obj ->ccc();
$obj ->bbb();

运行结果如下:

我是trait,我实现了ccc方法
我是B类的bbb方法

上面的代码可以继续优化一下

通过上面的用法, 我们就可以这样总结

  1. trait本质上还是一个类
  2. 接口(interface)规定了方法的定义, trait规定了方法的实现
  3. 可以认为A类D类等等其他类在需要ccc方法的时候包含了trait

综上, trait是PHP实现多继承的一种折中的方法, 姑且叫它"假多继承", 可以认为一个类(A类)包含了另一个类E(trait), 最终目的是为了实现代码复用.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值