欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

总是在重复,气抖冷,trait何时才能站起来?

程序员文章站 2022-04-02 21:38:52
...
类中的某些成员如何才能被其他类使用呢?使用继承的话,这继承链也太长了,为了方便,php提供了代码复用技术trait。

1.定义Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。trait可以使得单继承语言摆脱为了复用,而不得不继承的尴尬处境,让面向对象变得更加纯粹。

2.基础语法

trait是一种类似class的关键字。

<?php
     trait Eat{
        public $a=10;      //trait内允许有类的成员属性(包括静态属性),成员方法(包括静态方法)
        public static $b=666;
        //const c=3.14;       //trait内不允许有常量
        protected $e;	//允许定义,但是实际不用
        private $f;
        public function getA()
        {
               echo $this->a,"<br>";
        }
        public static function getB()
        {
               echo self::$b,"<br>";
        }
    }
?>

trait是用来实现代码的复用的,不可以被实例化也不可以被继承(因为根本不是类)。

<?php
   trait Eat{}
  // $a=new Eat;//报错
  //calss A extends Eat{}//报错
?>

3.trait的使用

trait只是一段代码的集合,使用时必须要使用use进行引用。

<?php
    
    trait Eat{
        public $a=10;
        public static $b=666;
        //const c=3.14;
        public function getA()
        {
               echo $this->a,"<br>";
        }
        public static function getB()
        {
               echo self::$b,"<br>";
        }
    }
    
    class A{
        use Eat;


        public function getC()
        {
            echo $this->a,"<br>";
        }
    }

    $boy=new A();
    $boy->getC();
    $boy->getA();
    $boy->getB();
?>

一个类可以使用多个trait。

<?php
   trait A1{
   }
   trait A2{
   }
   class People{
     use A1,A2;
   }
?>

4.trait使用的问题

a.如果同时引入的多个trait中有同名属性,那么会产生冲突。

<?php
    trait A1{
       public $a=11;
    }
    trait A2{
       public $a=22;
    }

    class A3{
        use A1,A2;//不允许同名属性
        public function geta(){
            echo $this->a;
        }
    }

    $example=new A3();
  

?>

b.如果同时引入的多个trait中有同名方法,那么会产生冲突,有两种方案解决如A3、A4。

<?php
    trait A1{
       public $a=11;
       public function eat(){
           echo "A1中eat()方法","<br>";
       }
    }
    trait A2{
       public $b=22;
       public function eat(){
        echo "A2中eat()方法","<br>";
      }
    }

    class A3{
        use A1,A2{
          A1::eat insteadOf A2; //A1中的eat替代A2中的eat
        }
    }
    class A4{
        use A1,A2{
            A1::eat insteadOf A2;//A1中的eat替代A2中的eat
            A2::eat as eat2;     //A2中的eat取别名eat2
          }
    }

    $example=new A3();
    $example->eat();
    $example=new A4();
    $example->eat2();
?>

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

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

  • 方法:类覆盖trait。

d.继承覆盖问题:如果类中在使用trait的同时,也是继承自父类,而trait中与父类中有同名方法,那么trait中将覆盖父类同名方法;如果要访问父类方法,可以在trait同名方法中使用parent关键字访问父类同名方法。

<?php
    trait Eat{
    public function eat(){
        echo 'Eat::eat';
    }
}
    class Human{
    public function eat(){
        echo 'Human::eat';
    }
}
//子类继承父类同时使用trait
class Man extends Human{
    use Eat;
}

$m = new Man();
$m->eat();
?>

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

<?php
trait Eat{
    private function show(){
        echo 'eat';
    }
}
class Human{
    use Eat{
        show as public eshow;				
        //注意:as是用来设定别名的,虽然没有同名show,但是系统认为show已经存在,所以必须别名,权限的更改的方法不是
        //本尊
    }
}
$h = new Human();
$h->eshow();								//eat
?>

f.trait中可以使用抽象方法,使用类必须实现对应抽象方法:使用类要么为抽象类,要么就必须实现抽象方法。

<?php
   trait Eat{
     public function eat();		//抽象方法
   }
   abstract class Human{			
    use Eat;					//抽象类:可以不实现抽象方法
   }

   class Animal{
    use Eat;
    public function eat(){		//具体类:实现抽象方法
        echo 'Animal::eat';	
    }		
}
?>

推荐:php教程,php视频教程

以上就是总是在重复,气抖冷,trait何时才能站起来?的详细内容,更多请关注其它相关文章!

相关标签: trait