首先重要的事情说三遍:
trait不是继承,和extends不一样。
trait不是继承,和extends不一样。
trait不是继承,和extends不一样。
请记住这个大前提,要不然在接下来的讲解中,你会很苦恼。会不断的问自己为什么,为什么!
1.用法
先上个实例:
<?php
trait trait1 {
public function ceshi(){
echo "ceshi";
}
}
class C1{
public function ceshi2(){
echo "ceshi2";
}
}
class C2 extends C1{
use trait1;
}
$aa = new C2();
$aa->ceshi();
$aa->ceshi2();
//输出ceshiceshi2
?>
按这个实例来讲解下,不说官方语言。其实就是把一个类的东西,完全复制到你的当前类中了。(或许底层不是这样的哈,但是在使用上,我就是这么理解 的。这也有助于接下来的理解,因为他和继承是不同的。记住!)
2.特性
优先性:
这个顺序在官方的解释是这样的:
官方是把trait中的方法和继承类也做了优先级对比。我告诉你,千万不要作对比。你会蒙圈,也因此需要多记几个东西。
你只要记住。trait的优先级没有本来的类中的方法高就可以了。如果 本来得类中有了trait中相同名字的方法按照本来的类的方法执行。至于继承的类,只要记住。那就是我继承类。因为trait属于本来的类的一部分了。所以对于继承来的类。就是普通继承的特性。
多个:
trait可以有多个,use a,b,c;
抽象成员:
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;
}
}
$a = new MyHelloWorld();
$a->setWorld('world');
$a->sayHelloWorld();
//输出 Hello world
?>
静态方法,静态变量:
静态方法就不说了,一样。静态变量是让我剧恶心的。上段代码自己看下!
可能 很多人一下 就能理解,不过我当时确实没理解,写出来一是给自己提个醒。也为那么蒙在水里的提个醒
<?php
trait Counter {
static $d = 1;
public function inc() {
static $c = 0;
$c = $c + 1;
echo "$c\n";
}
public function ww(){
self::$d++;
}
}
class C1 {
use Counter;
}
class C2 {
use Counter;
}
$o = new C1();
echo $o::$d;
$o->ww();
echo $o::$d;
$p = new C2();
echo $p::$d;
//输出 121
?>
对于这段代码我就在想为什么不说122。明明trait 都是counter啊。
为什么呢?因为counter已经被辅助到 c1 和 c2 里了 ,他已经变成两份了。互不干扰。
有人会说这有什么 可不明白的。很正常嘛!
那我在上一个代码
<?php
class a{
static $rr = 1;
}
class Person extends a{
function __construct() {
self::$rr++;
}
static function getId() {
return self::$rr;
}
}
class Person1 extends a{
function __construct() {
self::$rr++;
}
static function getId() {
return self::$rr;
}
}
echo Person::$rr; //output 0
echo Person1::$rr;
$p1=new Person();
echo $p1::$rr;
$p2=new Person1();
echo $p2::$rr;
//1123
?>
看到了吧,这就是我让你注意的,继承和trait 是不同的,就体现在这里。
多个不同的类继承同一个类,这个类的static 是一个。
多个不同的类use不同的trait,这个trait的static,已经被分成多个放到了每个类中。
这里要注意哈!
3.注意点
1.相同的方法名会被覆盖,可是相同的变量名会报有问题(完全相同的变量和赋值,7.0以下警告,7.0以上不报错。不过不要尝试这个东西,别给自己找trouble,好吧!)
4.解决冲突
1.方法冲突
就是本类和trait的方法名相同了。
<?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;
}
}
$dd = new Aliased_Talker();
$dd->bigTalk();
$dd->talk();
$dd->smallTalk();
//输出 ABb
?>
看代码我觉得聪明的你应该可以明白
讲解下两个关键的东西:
insteadof 前面的是要的 用签名的 替换掉 后面的
as 别名,很简单
trait这个东西在laravel用的很多,所以今天总结了一下