# 代码复用(Trait)

[官方文档](http://php.net/manual/zh/language.oop5.traits.php)

* trait 主要用于解决单继承引起的代码复用问题；
* 在类中使用 trait 类似于include一个公用文件；
* trait 支持所有修饰符例如 final，static，abstract
* trait 不能通过 new 实例化；
* trait 中的方法冲突可通过 insteadof 或 as 关键词解决。通过 as 还可修改访问权限。

**优先顺序示例**

从基类继承的成员被插入的 SayWorld Trait 中的 MyHelloWorld 方法所覆盖。其行为 MyHelloWorld 类中定义的方法一致。优先顺序是当前类中的方法会覆盖 trait 方法，而 trait 方法又覆盖了基类中的方法。

```php
<?php
class Base {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
}

class MyHelloWorld extends Base {
    use SayWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
?>
```

**多个 trait示例：**&#x901A;过逗号分隔，在 use 声明列出多个 trait，可以都插入到一个类中。

```php
<?php
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();
?>
```

以上例程会输出：

```
Hello World!
```

**trait中使用trait的示例**

正如 class 能够使用 trait 一样，其它 trait 也能够使用 trait。在 trait 定义时通过使用一个或多个 trait，能够组合其它 trait 中的部分或全部成员。

```php
<?php
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();
?>
```

以上例程会输出：

```
Hello World!
```

**trait中方法冲突问题示例：**

```php
<?php
trait firstTrait {
    function sameMethodName() { echo "method in firstTrait\n"; }
}

trait secondTrait {
    function sameMethodName() { echo "method in secontTrait\n"; }
}

class firstClass {
    // 使用firstTrait中的sameMethodName()方法而不是用secondTrait中的。:
    use firstTrait, secondTrait {
        firstTrait::sameMethodName insteadof secondTrait;
    }
}

$obj = new firstClass();

$obj->sameMethodName(); // Print : method in firstTrait
```

另一种方式

```php
<?php
trait firstTrait {
    function sameMethodName() { echo "method in firstTrait\n"; }
}

trait secondTrait {
    function sameMethodName() { echo "method in secontTrait\n"; }
}

class firstClass {
    use firstTrait, secondTrait {
        // 使用firstTrait中的sameMethodName()方法而不是用secondTrait中的。:
        firstTrait::sameMethodName insteadof secondTrait;
        // 使用secondTrait中的sameMethoName()方法但改名为 anotherMethodName():
        secondTrait::sameMethodName as public anotherMethodName;
    }
}

$obj = new firstClass();
$obj->sameMethodName(); 
$obj->anotherMethodName();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://phper.shujuwajue.com/php-gao-ji-te-xing/dai-ma-fu-752828-trait.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
