phptrait

发现php5开始就有trait了,但是从来没有使用过,特意了解了一下

traint是什么

trait是php的一种代码复用方法,和class相似与vue的组合函数类似,可以使用在多个地方,增加代码复用

trait定义和使用

//定义
trait name{
  function functioname1(){
    ...
  }
  function functioname2(){
    ...
  }
}
//使用
class clsname{
  use name;
}

trait需要在class里面使用关键词use来调用

如果trait中的方法名称一样的话,当前类中的方法会覆盖trait中的方法

trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}
class TheWorldIsNotEnough {
    use HelloWorld;
    public function sayHello() {
        echo 'Hello Universe!';
    }
}
$o = new TheWorldIsNotEnough();
$o->sayHello(); //Hello Universe!

多个trait可以使用逗号插入同一个类中

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中引入了同名的方法,可以使用insteadof方法来明确指定使用哪个,还可以使用as引入别名

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;
        B::bigTalk as talk;
    }
}
$t = new Talker();
$t->smallTalk(); //b
$t->bigTalk(); //A
$t->talk(); //B

trait可以支持抽象方法使用

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;
    }
}
$hello = new MyHelloWorld();
$hello->setWorld(' world!');
$hello->sayHelloWorld(); // Hello world!!

trait可以定义静态变量、方法、属性,8.2起可以定义常量

trait ConstantsTrait {
    public const FLAG_MUTABLE = 1;
    final public const FLAG_IMMUTABLE = 5;
}
class ConstantsExample {
    use ConstantsTrait;
}
$example = new ConstantsExample;
echo $example::FLAG_MUTABLE; // 1

php抽象方法和抽象类

在类中,没有方法体的方法就是抽象方法,类似: abstract function aaa();

抽象方法有什么用呢?

抽象方法在子类中必须要重写,这样就可以控制子类中必须包含某些方法 抽象类的作用类似,它不能被实例化,只能被继承

什么时候需要用抽象类?

有个方法,方法体不知如何写,子类中还必须有这个方法时,封装成抽象方法,类为抽象类。 控制子类中必须封装某些方法时,可以用抽象方法。 当需要控制类只能被继承,不能被实例化时。

如果一个类中,所有的方法都是抽象方法,且没有成员属性,则这个类被称为接口(interface)

interface Common{
    function work();
    function test($args);
}

接口继承接口 interface 接口名称 extends 父接口名称 类实现接口 class 类名 implements 接口名称1,接口名称2, … 类继承父类同时实现接口 class 类名 extends 父类名 implements 接口名称