【多继承】PHP使用trait或者是组合的模式来实现多继承【原创】

【多继承】PHP使用trait或者是组合的模式来实现多继承【原创】

PHP的类继承只能是单继承,不能多继承,如果想要实现多继承的话,可以使用接口的方式来多继承,但是如果不想使用接口的方式来实现多继承的话,可以考虑使用trait来实现,当然也可以使用组合模式来实现。trait是PHP 5.4新增的代码复用的方法,
Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

通常在类中使用 use关键字声明要组合的Trait名称,而具体某个Trait的声明使用trait关键词,Trait不能直接实例化。
代码如下:
1
<?php
2
/**
3
 * Traits可以多重继承,可以看做是一种加强型的接口
4
 */
5
 
           
6
trait Hello
7
{
8
    public function sayHello()
9
    {
10
        echo 'Hello ';
11
    }
12
 
           
13
    public function aaa()
14
    {
15
        echo 'AAA';
16
    }
17
}
18
 
           
19
trait World
20
{
21
    public function sayWorld()
22
    {
23
        echo 'World';
24
    }
25
}
26
 
           
27
class MyHelloWorld
28
{
29
    use Hello, World;
30
 
           
31
    public function sayExclamationMark()
32
    {
33
        echo '!';
34
    }
35
 
           
36
    // 会覆盖掉Hello中的aaa方法
37
    public function aaa()
38
    {
39
        echo 'AAAAA';
40
    }
41
}
42
 
           
43
$obj = new MyHelloWorld();
44
$obj->sayHello();
45
$obj->sayWorld();
46
$obj->sayExclamationMark();
47
$obj->aaa();
48
 
           
49
// 输出:
50
// Hello World!AAAAA
51
 
           
代码中使用两个trait来实现了多继承。
注意:两个trait中不能出现同样的方法,如果有同名的方法时,会产生致命错误。
注意:并且MyHelloWorld类中也有aaa方法,会覆盖Hello trait中的aaa方法。

上面的代码也可以通过组合的模式来实现,代码如下:
<?php
/**
 * 使用组合的方式也可以达到 1_12_trait.php 的效果
 */

class Hello2
{
    public function sayHello()
    {
        echo 'Hello ';
    }

    public function aaa()
    {
        echo 'AAA';
    }
}

class World2
{
    public function sayWorld()
    {
        echo 'World';
    }

    public function aaa()
    {
        echo 'AAAA';
    }
}

class MyHelloWorld2
{
    public $obj = [];

    public function __construct()
    {
        $this->obj['Hello2'] = new Hello2();
        $this->obj['World2'] = new World2();
    }

    public function sayExclamationMark()
    {
        echo '!';
    }

    public function __call($name, $arguments)
    {
        foreach ($this->obj as $value) {
            if (method_exists($value, $name)) {
               return $value->$name();
                // 也可以用 return call_user_func([$value, $name]);
            }
        }

        if (!method_exists($this->obj['Hello2'], $name) && !method_exists($this->obj['World2'], $name)) {
            echo "\r\n不存在此方法";
        }

        return true;
    }

    // 会覆盖其他类的aaa方法
    public function aaa()
    {
        echo 'AAAAA';
    }
}

$obj = new MyHelloWorld2();
$obj->sayHello();
$obj->sayWorld();
$obj->saywhat();
$obj->aaa();
$obj->sayExclamationMark();

// 输出:
// Hello World!AAAAA


显而易见,通过trait来实现的话代码量少得多并且可读性也要高得多。




posted @ 2017-07-06 15:15 Newman·Li 阅读( ...) 评论( ...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值