Menu
Coddy logo textTech

トレイトの概要

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クラス、またはタイムスタンプ機能を必要とするその他のクラスです。これにより、クラス階層全体で水平方向のコード共有が可能になり、単一継承の制限を解消できます。

challenge icon

チャレンジ

簡単

trait を使うと、互いに無関係な class 間で機能を共有できることを示す、シンプルな挨拶システムを構築しましょう。挨拶機能を提供する trait を作成し、それをまったく異なる2つの class で使用します。

コードを3つのファイルに分けて整理します。

  • Greetable.php: 挨拶機能を提供する Greetable という trait を Create します。この trait には次の要素を含めます。
    • private property $greeting(string)
    • 挨拶メッセージを stores する setGreeting(string $greeting) method
    • 挨拶メッセージを returns する greet() method
  • Person.php: Greetable trait を使用する Person class を Create します。trait ファイルを読み込み、constructor promotion を使って public $name property を define します。constructor では、setGreeting() を call して、挨拶を "Hello, I'm [name]" に設定します。
  • Robot.php: 同じく Greetable trait を使用する Robot class を Create します。trait ファイルを読み込み、constructor promotion を使って public $model property を define します。constructor では、setGreeting() を call して、挨拶を "Beep boop, I am model [model]" に設定します。

main.php では、両方の class ファイルを読み込みます。2つの入力として、person の名前と robot の model 番号を受け取ります。両方の class のインスタンスを Create し、それぞれの挨拶を別々の行に Print します。

これは trait の力を示しています。PersonRobot は共通の親を持たない、完全に無関係な 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の挨拶を出力する(新しい行に)

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: PHPオンラインコンパイラ