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

PHP的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), 最终目的是为了实现代码复用.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值