<?php
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();//先调用父类的sayHello
echo 'World!<br/>';
}
}
class MyHelloWorld1 extends Base {
use SayWorld;
}
$o = new MyHelloWorld1();
$o->sayHello();
echo "<hr>";
echo "为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个<br/>
在本例中 Talker 使用了 trait A 和 B。由于 A 和 B 有冲突的方法,其定义了使用 trait B 中的 smallTalk 以及 trait A 中的 bigTalk。
Aliased使用了 as 操作符来定义了 talk 来作为 B 的 bigTalk 的别名。";
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 Alias {
use A, B {
B::smallTalk insteadof A;//insteadof 代替
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}
$o=new Alias();
$o->smallTalk();
$o->bigTalk();
$o->talk();
echo "<hr>";
echo "修改方法的访问控制
使用 as 语法还可以用来调整方法的访问控制。<br/>";
trait Hello_ {
public function sayHello() {
echo 'Hello World!<br/>';
}
}
// 修改 sayHello 的访问控制
class MyClass1 {
use Hello_{ sayHello as public;}//protected/private
}
// 给方法一个改变了访问控制的别名
// 原版 sayHello 的访问控制则没有发生变化
class MyClass2 {
use Hello_ { sayHello as public new_name; }
}
$o=new MyClass1();
$o->sayHello();
$o=new MyClass2();
$o->new_name();
echo "<hr>";
echo "用 trait 来组成 trait 意思是,用N个trait 组成一个trait<br/>";
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World!';
}
}
trait HelloWorld {
use Hello, World;
}
class MyHelloWorld {
use HelloWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
echo "<hr>为了对使用的类施加强制要求,trait 支持抽象方法的使用。";
trait Hello2 {
public function sayHelloWorld() {
echo 'Hello'.$this->getWorld();
}
abstract public function getWorld();
}
class MyHelloWorld2 {
private $world;
use Hello2;
public function getWorld() {
return $this->world;
}
public function setWorld($val) {
$this->world = $val;
}
}
echo "<hr>raits 可以被静态成员静态方法定义。<br/>";
trait Counter {
public function inc() {
static $c = 0;
$c = $c + 1;
echo "$c
";
}
}
class C1 {
use Counter;
}
class C2 {
use Counter;
}
$o = new C1(); $o->inc(); // echo 1
$p = new C2(); $p->inc(); // echo 1
echo "Example #10 静态方法<br/>";
trait StaticExample {
public static function doSomething() {
return 'Doing something';
}
}
class Example {
use StaticExample;
}
Example::doSomething();
echo "Trait 定义了一个属性后,类就不能定义同样名称的属性,否则会产生 fatal error。 有种情况例外:属性是兼容的(同样的访问可见度、初始默认值)。 在 PHP 7.0 之前,属性是兼容的,则会有 E_STRICT 的提醒。
Example #12 解决冲突";
trait PropertiesTrait {
public $same = true;
public $different = false;
}
class PropertiesExample {
use PropertiesTrait;
public $same = true; // PHP 7.0.0 后没问题,之前版本是 E_STRICT 提醒
public $different = true; // 致命错误
}