• 【多继承】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 "
    不存在此方法";
            }
    
            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来实现的话代码量少得多并且可读性也要高得多。




  • 相关阅读:
    Oracle9使用oradata恢复数据库
    我该怎么安排下属的工作项目经理如何分配任务
    如果说中国的程序员技术偏低,原因可能在这里
    项目经理问:为什么总是只有我在加班 – 挂包袱现象
    【转】面试真经
    [JAVA]PING和TELNET用法介绍
    Hello World 你懂的
    线程间操作控件
    获取客户端相关信息
    winfrom 特效 [转载]
  • 原文地址:https://www.cnblogs.com/linewman/p/9918117.html
Copyright © 2020-2023  润新知