zoukankan      html  css  js  c++  java
  • php继承---trait代码复用

     思考:php中继承是单继承,如果某个类有成员要被其他类使用,就需要称为其他类的父类才行,这样可能会导致继承链会长,合适吗?

    引入:哦那个继承的角度触发,继承链可以解决问题,但是的确效率会打折扣,同时,如果某些功能是共性使用,但是并不符合继承条件(不属于同一类)

    那么使用继承也有所违背面上对象规则,此时可以使用php提供的另外一种代码复用技术trait

    trait代码复用【掌握】

    定义:trait是为类似php的单继承语言而准备的一种代码复用机制,trait可以使得但继承语言为了复用而不得不继承的尴尬,让面向对象更加纯粹

    1.trait是一种类似class的关键字

    <?php
    
    
    // 定义trait
    trait show{
    
    }

    2.trait内部可以像类一样拥有成员属性(包含静态),成员方法(包含静态),但不能有常量

    <?php
    
    
    // 定义trait
    trait show{
        public $name;
    
        protected $host;                           //允许定义,但实际不用
        private $info; 
    
        public function show_time(){ 
            echo $this->info;
        }
    
        protected function showhost(){                //允许定义,但实际不用
            echo $this->name;
        }
    
        const pi=3.1415926;                //错误  trait中不能有常量
    }

    3.trait是用来实现代码的复用的,不可以被实例化也不可以被继承

    <?php
    
    
    // 定义trait
    trait show{
        public $name;
    
        protected $host;                           //允许定义,但实际不用
        private $info; 
    
        public function show_time(){ 
            echo $this->info;
        }
    
        protected function showhost(){                //允许定义,但实际不用
            echo $this->name;
        }
    
    
    }
    
    
    new show();                //trait 不允许被实例化

    4.trait是用来将公共代码提供给其他类使用的,而类要使用trait的掐你是加载对应的trait

    <?php
    
    
    // 定义trait
    trait Show{
        public $name="d";
        public function show_time(){ 
            echo $this->name;
        }
    
    }
    
    
    
    //类中加载trait
    class add{
        //加载:使用use关键字
        use Show;           //use 就表示将trait show中所有的东西拿到了当前类add中
    }
    
    
    //使用trait中的内容
    $s=new add();
    $s->show_time();                //show add类中自己没有show_time方法,但是因为使用了trait show 所以可用

    5.一个类可以使用多个trait

    <?php
    
    
    // 定义trait
    trait Show{
        public $name="d";
        public function show_time(){ 
            echo $this->name;
        }
    
    }
    
    trait get{
        public $age=18;
    
        public function get_age(){
            echo $this->age;
        }
    }
    
    
    
    //类中加载trait
    class add{
        //加载:使用use关键字
        use Show;           //use 就表示将trait show中所有的东西拿到了当前类add中
        use get;
    }
    
    
    //使用trait中的内容
    $s=new add();
    $s->show_time();                //show add类中自己没有show_time方法,但是因为使用了trait show 所以可用
    $s->get_age();

     6.如果同时引入的多个trait中有同名方法,那么会产生冲突:解决冲突的方法是使用insteadof代替处理以及对被代替的方法使用别名

    <?php
    
    
    // 定义trait
    trait show{
        public $name="d";
        public function show_time(){ 
            echo $this->name;
        }
    
    }
    
    trait get{
        public $age=18;
    
        public function show_time(){
            echo $this->age;
        }
    }
    
    
    
    //类中加载trait
    class add{
    
        // use get,show;                 //错误 2个trait存在同名的方法
    
        // 方案1 使用其中一个同名方法
        use get,show{
            // 意思 使用show中的show_time 代替get中的show_time,并且会被覆盖无法使用
            show::show_time insteadOf get;
            // 方案2 给get中的show_time取一个别名  就可以使用了。
            get::show_time as show_insteadostime;
        }
    }
    
    $s=new add();
    $s->show_time();            //输出的是d  而不是18  代替成功
    $s->show_insteadostime();       //显示18

    7.同名覆盖问题:如果类中有与引入的trait同名成员,会有不同处理

      属性:不允许重名,即类中不允许定于与trait中同名的成员属性(静态属性也一样)

      方法:类覆盖trait

    <?php
    
    
    // 定义trait
    trait show{
        public $name="d";
        public function show_time(){ 
            echo $this->name;
        }
    
    }
    
    trait get{
        public $age=18;
    
        public function show_time(){
            echo $this->age;
        }
    }
    
    
    
    //类中加载trait
    class add{
    
        // use get,show;                 //错误 2个trait存在同名的方法
    
        // 方案1 使用其中一个同名方法
        use get,show{
            // 意思 使用show中的show_time 代替get中的show_time,并且会被覆盖无法使用
            show::show_time insteadOf get;
            // 方案2 给get中的show_time取一个别名  就可以使用了。
            get::show_time as show_insteadostime;
        }
    }
    
    $s=new add();
    $s->show_time();            //输出的是d  而不是18  代替成功
    $s->show_insteadostime();       //显示18

    8.继承覆盖问题:如果类中在使用trait的同时,也是继承自父类,而trait中与父类中有同名方法,那么trait中将覆盖父类同名方法,如果要访问父类方法,

    可以在trait同名方法中使用parent关键字访问父类同名方法。

    <?php
    
    // 代码复用
        trait posen{
            public $name="杜伟";
            public $age=31;
    
            public function show(){
             // 如果想用父类中的方法
             parent::show();
                echo $this->name.$this->age;
            }
        }
    
    
    // 父类
    class human{
        public function show(){
    
            echo 'human::show<hr>';
        }
     
    }
    
    // 定义子类
    class son extends human{
        use posen;              
    }
    
    // 实例化
    $s=new son();
    $s->show();               //显示的是杜伟 31  trait中的方法会覆盖继承中父类的方法

    9.另外,trait自己不能访问,只是用来给其他类提供代码复用的,因此允许类在使用trait时更高里面方法的访问控制权。在as 之后,使用目标访问修饰限定符。

    <?php
    
    // 代码复用
        trait posen{
            private function show(){
                echo '你看到我了';
            }
        }
    
    class son{
        use posen{
            //因为我只是引用了一个show,如果是两个的话  需要具体的体现是哪个 posen::show(这个)
            show as public pshow;              
            //注意 as是用来起别名的,虽然没有同名show 但是系统认为已经存在,并且改变trait中show的访问权限为public 变成了一个新的方法,原来的方法不动。
        }              
    }
    
    // 实例化
    $s=new son();
    $s->pshow();           //调用别名方法

    10.trait中可以使用抽象方法,用来规范使用类必须实现对应抽象方法,使用了欸要么为抽象类,要么就必须实现抽象方法

    <?php
    
    // 代码复用
        trait posen{
           abstract public function add();            //trait 定义抽象方法
        }
    
    
    // 第一种方式
    abstract class man{
        use posen;                          //抽象类可以不实现抽象方法
    }
    
    // 第二种
    class son{
        use posen;
        public function add(){
            echo '实现了trait中的抽象方法';          //实现抽象方法
        }
                    
    }

    总结:

      1.trait的hi一种类似class结构关键字,trait不能被实例化,可以拥有所有类成员结构

      2.trait是用来实现代码复用的,为其他类提供公共代码(方法),其他类如果使用trait用use关键字引入

      3.在了类中use是具体trait就相当于将trait内部的所有代码在类中写了一遍

      4.一个类中可以有多个trait,但是要注意同名问题

        同名方法可以使用insteadof来实现代替:一个trait中的同名方法代替另外一个,类就访问替代的那个

        同名方法可以在被替代之后使用as制作方法使用as制作方法别名:类就可以拥有两个方法

      5.类中在引入trait后,要注意与trait中的同名成员问题

        同名属性:不允许

        同名方法:允许,类中的方法会覆盖trait中的方法

      6.如果在使用trait的同时也继承其他类,那么trait中出现的同名方法会覆盖基类的同名方法

      7.类在使用trait时可以修改trait方法的控制级别,更严或这更宽松都可以,注意修改控制级别时使用的时别名机制,一定要改成别名:trait名::方法名 as 访问修饰限定符 别名;

      8.trait中可以使用抽象方法,那么使用该trait的类就必须本身为抽象类或者将抽象方法实现

      9.trait使用机制

        有公共代码要实现(方法),而这些方法可能在很多类中会用到

        公共代码不是属于某一类事务特有,而是很多事务都有(不符合继承)

  • 相关阅读:
    search for a range
    search in rotated sorted array
    MSDN--Windows Server
    Windows Server 2016- Windows Server 2016 上 HYPER-V 中的新增功能
    Azure 媒体服务产品简介
    EMC Avamar Virtual Edition 7.1.1 for Microsoft Azure and Hyper-V Released
    漫游用户配置文件 -文件夹重定向
    How to Install office 365 Plus without ODT
    Azure IoT
    AD FS deployment in Azure
  • 原文地址:https://www.cnblogs.com/xiaowie/p/12303583.html
Copyright © 2011-2022 走看看