Skip to content

PHP 类和对象之 Trait #70

@huliuqing

Description

@huliuqing

PHP 类和对象之 Trait

Trait 文档
PHP 仅支持单继承(即仅能继承 extends 一个父类),Trait 功能提供类似于多继承的功能

Trait 定义和使用与 clss 相同,只不过声明关键字用 trait 而非 class,另外 trait 不能实例化

优先级

当前类、基类和 Trait 存在相同方法时的优先级关系如下:

当前类方法 > Trait > 基类

使用 Trait

在类声明内使用关键字 use 引入 Trait

<?php
trait A
{
}

trait B
{
}

class Test 
{
	use A, B;
}

Trait 语法特性

  • 可以定义 abstract 方法
  • 支持静态属性和方法
  • 支持静态成员
  • 使用 trait 的类,不能定义与 trait 内定义的同名属性(fatal error)
    但如果可见性及初始值相同的属性可以定义即属性兼容

冲突解决和别名

  • 两个Trait 有相同方法的冲突解决: 在当前类中使用 insteadof 操作符指明使用哪个方法
  • 为 Trait 中的方法声明别名:在当前类中使用 as 引入别名,此时会在当前类中存在别名方法和 Trait 中定义的方法
<?php
trait A
{
    public function hi()
    {
        echo 'hi from A' . PHP_EOL;
    }
}

trait B
{
    public function hi()
    {
        echo 'hi from B' . PHP_EOL;
    }
}

class Test 
{
    use A, B {
        //指明实例调用 hi() 方法使用 Trait A 中的 hi() 而非 Trait B 中的 hi()
        A::hi insteadof B;        

        // 在当前类引入 hi 的别名方法 sayHi, 也可以声明别名方法的访问权限
        A::hi as /*protected*/ sayHi;
        
        //将 Trait B 中的 hi 引入 hello 的别名
        B::hi as hello;
    }
}

$test = new Test();
$test->hi();
$test->sayHi();
$test->hello();

// var_dump(get_class_methods('Test'));
// print: 
// array(3) {
//   [0]=>
//   string(5) "sayHi"                      
//   [1]=>
//   string(2) "hi"                      
//   [2]=>
//   string(5) "hello"                                 
// } 

参考资料

如何使用Trait?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions