什么是 trait
看看 PHP 官网的介绍.
自 PHP 5.4.0 起, PHP 实现了一种代码复用的方法, 称为 trait.
Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制. Trait 为了减少单继承语言的限制, 使开发人员能够自由地在不同层次结构内独立的类中复用 method.Trait 和 Class 组合的语义定义了一种减少复杂性的方式, 避免传统多继承和 Mixin 类相关典型问题.
Trait 和 Class 相似, 但仅仅旨在用细粒度和一致的方式来组合功能. 无法通过 trait 自身来实例化. 它为传统继承增加了水平特性的组合; 也就是说, 应用的几个 Class 之间不需要继承.
例子 1
手机和汽车都有 GPS 功能, GPS 是用来定位的功能的, 因此功能应该是统一的. 手机 和 汽车 除了 GPS 功能外, 基本没有什么相同之处, 因此不能使用继承. 而接口的话, 我认为不同的类去实现接口时, 接口的实现可能是不同的, 但是 GPS 的功能就是用来定位的. 因此使用 trait , 而不使用 class 和 interface, 这是我的理解, 不知道是否正确.
gps.php 的定义:
- <?php
- trait Gps { public function gps() {
- echo 'i can gps';
- }
- }
使用 trait 定义了一个 GPS 的 trait 用于复用, 它的关键字是 trait . 然后在 car.php 和 mobile.php 中进行引用.
car.php 的定义:
- class Car {
- use gps;
- public function move() {
- echo 'i can move';
- }
- }
mobile.php 的定义:
- <?php
- class Mobile {
- use gps;
- public function tel() {
- echo 'i can tel';
- }
- }
在 car.php 和 mobile.php 中, 使用 use 关键字引入了 gps 的 trait , 这样在 car 和 mobile 中就可以调用 gps() 这个方法了.
test.php 进行测试:
- <?php
- require_once('gps.php');
- require_once('car.php');
- require_once('mobile.php');
- $car = new Car();
- $mobile = new Mobile();
- $car->gps();
- echo "\n";
- $mobile->gps();
输出结果如下:
- i can gps
- i can gps
例子 2
在 car 中引入了另外一个国产的 gps .
gpschina.php 定义如下:
- <?php
- trait GpsChina {
- public function gps() {
- echo 'i can chinae gps';
- }
- }
在 car 中引入, 修改 car.php 的定义如下:
- <?php
- class Car {
- use gps, gpschina;
- public function move() {
- echo 'i can move';
- }
- }
再次调用 test.php 进行测试, 这时会报错, 报错如下:
1 Fatal error: Trait method gps has not been applied, because there are collisions with other trait methods on Car in Car.php on line 4
因为在引入的 trait 中 gps 和 gpschina 各有一个 gps , 而直接使用 $car->gps() 时无法确定到底使用的是 gps 的 gps() 方法, 还是使用的 gpschina 的 gps() 方法, 因此报错了. 这样的话, 我们需要确定一个. 修改 car.php 文件.
- <?php
- class Car {
- use gps, gpschina {
- GpsChina::gps insteadof Gps;
- }
- public function move() {
- echo 'i can move';
- }
- }
这样就使用 GpsChina::gps 的方法 替换掉了 Gps 的方法了, 在调用 test.php 进行查看.
- i can chinae gps
- i can gps
这样, 对于 $car->gps() 后就调用了 gpschina 中的 gps() 方法了.
例子 3
如果在 Car 类中本身有一个 gps() 方法呢? 修改 Car 类.
- <?php
- class Car {
- use gps, gpschina {
- GpsChina::gps insteadof Gps;
- }
- public function gps() {
- echo 'car::gps';
- }
- public function move() {
- echo 'i can move';
- }
- }
调用 test.php 查看结果:
- car::gps
- i can gps
可以看出, 调用了 Car 类本身的 gps() 方法.
如果在一个类中, 继承自父类的方法, use 引入 trait 的方法 和 类自身的方法同名的话, 优先调用 自身类的 方法, 如果没有 自身类的方法 则调用 use 引入 trait 的方法, 如果前两个都没有, 那么就调用继承自父类的方法.
关于 trait 更多的用法, 请参考: http://www.php.net/manual/zh/language.oop5.traits.php
来源: http://www.bubuko.com/infodetail-2765502.html