php面向对象之trait

在学习laravel的时候总是看到代码中使用了trait,下面结合网上的资料谈谈我的理解加深印象

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

说简单一点就是php是单继承语言,一个类只能继承一个基类,但如果你还想这个类继承其他类的属性或方法,就可以通过trait解决。
定义格式

trait Name{
   public $arr;
   public function test(){};
   ....
}

几乎和类的定义方式一样,但trait不是类因此trait不能实例化
调用格式

class ClassName {
    use traitName;
}

如下实例



trait Person{
    public function walk(){
    	echo "person----walk";
    }
}

class Animal {
	public function eat(){
		echo "animal----eat";
	}
}

class Dog extends Animal{
	use Person;
	public function wang(){
		echo "wangwangwang";
	}
}

$dog1 = new Dog();
$dog1->eat();//animal----eat
$dog1->wang();//wangwangwang
$dog1->walk();//person----walk

Dog继承了Animal中的方法同时还可以调用trait Person中的方法

优先级
测试trait与基类本类方法重名


trait Person{
    public function walk(){
    	echo "person----walk";
    }
    public function test(){
    	echo "person----test";
    }
}

class Animal {
	public function eat(){
		echo "animal----eat";
	}
	public function walk(){
		echo "animal----walk";
	}
}

class Dog extends Animal{
	use Person;
	public function wang(){
		echo "wangwangwang";
	}
	public function test(){
		echo "Dog----test";
	}
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "
"
; $dog1->walk();//person----walk

当trait与基类的方法重名时trait方法会覆盖基类中的方法,当trait中的方法与本来重名时本类中的方法会覆盖trait中的方法即
本类>trait>基类

在trait中定义了属性,基类或本类就不能使用同名属性,反之报错但是在PHP 7.0.0之后只要属性的初始值以及可见性一致的时候会正常运行


trait Wuman{
	public $name = 12;
	public function sky(){
		echo "wuman----sky";
	}
}
class Dog {
	// public $name = 'animal';
	use Wuman;
    public $name = 12;
    protected $name = 12;//可见性不一样报错
    public $name = 13;//初始值不一样报错
	public function wang(){
		echo "wangwangwang";
	}
	public function test(){
		echo "Dog----test";
	}
}

$dog1 = new Dog();
$dog1->test();//Dog----test

多个trait
类里面可以使用多个trait通过逗号分隔即可


trait Human{
	public function show(){
		echo "human----show";
	}
}
trait Person{
	public $name = 'human';
    public function walk(){
    	echo "person----walk";
    }
    public function test(){
    	echo "person----test";
    }
}

class Animal {

	public function eat(){
		echo "animal----eat";
	}
	public function walk(){
		echo "animal----walk";
	}
}

class Dog extends Animal{
	// public $name = 'animal';
	use Person,Human;

	public function wang(){
		echo "wangwangwang";
	}
	public function test(){
		echo "Dog----test";
	}
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "
"
; $dog1->walk();//person----walk $dog1->show();//walkhuman----show

但是多个trait难免会遇到方法重名的问题,这里通过insteadof替换 和 as取别名的方式解决


trait Human{
	public function show(){
		echo "human----show";
	}
}
trait Person{
	public $name = 'human';
    public function walk(){
    	echo "person----walk";
    }
    public function test(){
    	echo "person----test";
    }
    public function show(){
    	echo "Person---show";
    }
}


class Dog {
	// public $name = 'animal';
	use Person,Human{
		Person::show insteadof Human;
	}
	public function wang(){
		echo "wangwangwang";
	}
	public function test(){
		echo "Dog----test";
	}
}
$dog1 = new Dog();
$dog1->test();//Dog----test
echo "
"
; $dog1->walk();//person----walk echo "
"
; $dog1->show();//Person----show

上面代码通过insteadof使HumanPerson的同名方法优先执行Person所以程序输出person----show,此时如果还想使用Human中的show方法可通过as取别名的方式


trait Human{
	public function show(){
		echo "human----show";
	}
}
trait Person{
	public $name = 'human';
    public function walk(){
    	echo "person----walk";
    }
    public function test(){
    	echo "person----test";
    }
    public function show(){
    	echo "Person---show";
    }
}


class Dog {
	// public $name = 'animal';
	use Person,Human{
		Person::show insteadof Human;
		Human::show as huShow;

	}

	public function wang(){
		echo "wangwangwang";
	}
	public function test(){
		echo "Dog----test";
	}
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "
"
; $dog1->walk();//person----walk echo "
"
; $dog1->show();//Person----show echo "
"
; $dog1->huShow();//human----show

使用 as 语法还可以用来调整方法的访问控制

use Person,Human{
	Person::show insteadof Human;
	Human::show as private huShow;
}

trait中使用trait


trait Wuman{
	public function sky(){
		echo "wuman----sky";
	}
}
trait Human{
	use Wuman;
	public function show(){
		echo "human----show";
	}
}
trait Person{
	public $name = 'human';
    public function walk(){
    	echo "person----walk";
    }
    public function test(){
    	echo "person----test";
    }
    public function show(){
    	echo "Person---show";
    }
}
class Dog {
	// public $name = 'animal';
	use Person,Human{
		Person::show insteadof Human;
		Human::show as  huShow;

	}

	public function wang(){
		echo "wangwangwang";
	}
	public function test(){
		echo "Dog----test";
	}
}

$dog1 = new Dog();
$dog1->test();//Dog----test
echo "
"
; $dog1->walk();//person----walk echo "
"
; $dog1->show();//Person----show echo "
"
; $dog1->huShow();//human----show echo "
"
; $dog1->sky();//wuman----sky

trait中的抽象类
trait中可以使用抽象类对类施加强制要求


trait Wuman{
	public function sky(){
		echo "wuman----sky";
	}
	abstract public function test();
}
class Dog {
	// public $name = 'animal';
	use Wuman;

	public function wang(){
		echo "wangwangwang";
	}
	public function test(){
		echo "Dog----test";
	}
}

$dog1 = new Dog();
$dog1->test();//Dog----test

你可能感兴趣的:(php)