トレイトの概要
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 51/91。
PHP は単一継承のみをサポートします。つまり、class は 1 つの親 class だけを拡張できます。しかし、互いに無関係な複数の class 間で機能を共有する必要がある場合はどうでしょうか? そこで trait の出番です。
trait は、複数のクラスに挿入できるメソッドやプロパティを定義できる、コード再利用のための仕組みです。trait は言語レベルでのコピー&ペーストだと考えてください。trait のコードは、それを使用するクラスの一部になります。
<?php
trait Timestampable {
private string $createdAt;
public function setCreatedAt(): void {
$this->createdAt = date('Y-m-d H:i:s');
}
public function getCreatedAt(): string {
return $this->createdAt;
}
}
class Article {
use Timestampable;
public function __construct(public string $title) {
$this->setCreatedAt();
}
}
$article = new Article("PHP Traits");
echo $article->getCreatedAt();
use キーワードを class 内で使うと、trait のメンバーがインポートされます。これで Article は、setCreatedAt() と getCreatedAt() に、あたかも class 内で直接定義されているかのようにアクセスできます。
同じtraitは、まったく関連のないクラスでも使用できます。たとえば、Commentクラス、Userクラス、またはタイムスタンプ機能を必要とするその他のクラスです。これにより、クラス階層全体で水平方向のコード共有が可能になり、単一継承の制限を解消できます。
チャレンジ
簡単trait を使うと、互いに無関係な class 間で機能を共有できることを示す、シンプルな挨拶システムを構築しましょう。挨拶機能を提供する trait を作成し、それをまったく異なる2つの class で使用します。
コードを3つのファイルに分けて整理します。
Greetable.php: 挨拶機能を提供するGreetableという trait を Create します。この trait には次の要素を含めます。- private property
$greeting(string) - 挨拶メッセージを stores する
setGreeting(string $greeting)method - 挨拶メッセージを returns する
greet()method
- private property
Person.php:Greetabletrait を使用するPersonclass を Create します。trait ファイルを読み込み、constructor promotion を使って public$nameproperty を define します。constructor では、setGreeting()を call して、挨拶を"Hello, I'm [name]"に設定します。Robot.php: 同じくGreetabletrait を使用するRobotclass を Create します。trait ファイルを読み込み、constructor promotion を使って public$modelproperty を define します。constructor では、setGreeting()を call して、挨拶を"Beep boop, I am model [model]"に設定します。
main.php では、両方の class ファイルを読み込みます。2つの入力として、person の名前と robot の model 番号を受け取ります。両方の class のインスタンスを Create し、それぞれの挨拶を別々の行に Print します。
これは trait の力を示しています。Person と Robot は共通の親を持たない、完全に無関係な class ですが、trait を通じて同じ挨拶機能を獲得します。それぞれの class は、その機能を独自の方法でカスタマイズして使用します。
自分で試してみよう
<?php
require_once 'Person.php';
require_once 'Robot.php';
// 入力を読み取る
$name = trim(fgets(STDIN));
$model = trim(fgets(STDIN));
// TODO: 与えられた名前でPersonインスタンスを作成する
// TODO: 与えられたモデルでRobotインスタンスを作成する
// TODO: Personの挨拶を出力する
// TODO: Robotの挨拶を出力する(新しい行に)
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: PHPオンラインコンパイラ