zoukankan      html  css  js  c++  java
  • PHP Trait 解决 PHP 单继承问题

    什么是继承?

    继承实际上是存在于面向对象程序设计中的两个类之间的一种关系,是面向对象程序设计方法的一个重要手段,通过继承可以更有效地组织程序结构,明确类间的关系,充分利用已有的类来完成更复杂、更深入的开发。

    当一个类拥有另一个类的所有数据和操作时,就称这两个类之间具有继承关系。

    被继承的类称为父类,继承了父类的所有数据和操作的类称为子类。

    在 PHP 中用 extends 表明子类与父类的继承关系。

    在面向对象的程序设计中,采用继承的方式来组织设计系统中的类,可以提高程序的抽象程度,更接近人的思维方式,使程序结构更清晰并降低编码和维护的工作量。

    • 单继承是指任何一个类都只有一个单一的父类,其结构可以用单纯的树状结构来表示;
    • 多继承是指一个类可以有一个以上的父类,它的静态的数据属性和操作从所有这些父类中继承,其结构应以复杂的网状结构来表示。

    PHP 仅支持单继承,而多继承是通过接口或者 Trait 来实现的。

    PHP 的单继承示例:

    // 单继承:一个子类只能有一个父类
    class A{
        function show() {
            echo "A";
        }
    }
    
    class B{
        function show() {
            echo "B";
        }
    }
    
    class C extends A{
    
    }
    
    $c = new C;
    $c->show();

    使用 Trait 解决 PHP 的单继承

    自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。

    • Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制
    • Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method
    • Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题
    • 无法通过 trait 自身来实例化

    示例:

    <?php
       trait Reader{
          public function add($var1,$var2){
             return $var1+$var2;
          }
       }
       trait writer {
          public function multiplication($var1,$var2){
             return $var1*$var2;
          }
       }
       class File {
          use Reader;
          use writer;
          public function calculate($var1,$var2){
             echo "Ressult of addition:".$this->add($var1,$var2) ."
    ";
             echo "Ressult of multiplication:".$this->multiplication($var1,$var2);
          }
       }
       $o = new File();
       $o->calculate(5,3);

    多个 trait

    通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。

    <?php
    trait Hello {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait World {
        public function sayWorld() {
            echo 'World';
        }
    }
    
    class MyHelloWorld {
        use Hello, World;
        public function sayExclamationMark() {
            echo '!';
        }
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();
    $o->sayExclamationMark();

    冲突的解决

    如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。

    为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。

    以上方式仅允许排除掉其它方法,as 操作符可以 为某个方法引入别名。 注意,as 操作符不会对方法进行重命名,也不会影响其方法。

    示例:

    <?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;
        }
    }

    从 trait 来组成 trait

    正如 class 能够使用 trait 一样,其它 trait 也能够使用 trait。在 trait 定义时通过使用一个或多个 trait,能够组合其它 trait 中的部分或全部成员。

    <?php
    trait Hello {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait World {
        public function sayWorld() {
            echo 'World!';
        }
    }
    
    trait HelloWorld {
        use Hello, World;
    }
    
    class MyHelloWorld {
        use HelloWorld;
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();

    Trait 的抽象成员

    为了对使用的类施加强制要求,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;
        }
    }

    Trait 的静态成员

    Traits 可以被静态成员静态方法定义。

    <?php
    // 静态成员 trait Counter {
    public function inc() { static $c = 0; $c = $c + 1; echo "$c "; } } class C1 { use Counter; } class C2 { use Counter; } $o = new C1(); $o->inc(); // echo 1 $p = new C2(); $p->inc(); // echo 1
    <?php
    // 静态方法
    trait StaticExample {
        public static function doSomething() {
            return 'Doing something';
        }
    }
    
    class Example {
        use StaticExample;
    }
    
    Example::doSomething();
    <?php
    // 定义属性
    trait PropertiesTrait {
        public $x = 1;
    }
    
    class PropertiesExample {
        use PropertiesTrait;
    }
    
    $example = new PropertiesExample;
    $example->x;

    参考:

    https://www.php.net/manual/zh/language.oop5.traits.php

    https://learnku.com/php/t/37694

    https://www.tutorialspoint.com/what-is-traits-in-php

    原文地址:

    https://www.ryanzoe.top/php/%e9%9d%a2%e5%90%91%e5%af%b9%e8%b1%a1/php-trait/ 

  • 相关阅读:
    基于Lumisoft.NET实现的邮件发送功能
    jqueryautocomplete 使用手册
    asp.net访问网络路径方法模拟用户登录
    JavaScript判断浏览器类型及版本
    解决jquery.autocomplete在IE6下被下拉框遮住的问题
    How to resovle aspnet_merge.exe error issue in web deployment project
    敏捷开发之Scrum扫盲篇
    JS 异常: Uncaught RangeError: Maximum call stack size exceeded
    HTTP请求的 转发 重定向 代理
    JS跨域访问 控制
  • 原文地址:https://www.cnblogs.com/ryanzheng/p/12731220.html
Copyright © 2011-2022 走看看