Skip to content

PHP 类和对象之 Trait #70

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?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions