Menu
Coddy logo textTech

複数のトレイトの使用

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 52/91。

単一のtraitも便利ですが、真の力は、1つのclassで複数のtraitを組み合わせたときに発揮されます。PHPでは必要な数だけtraitを含めることができるため、複数のソースから機能を同時にclassへ追加できます。

複数のトレイトを使用するには、useキーワードの後にコンマで区切って列挙するだけです:

<?php
trait Timestampable {
    public function getTimestamp(): string {
        return date('Y-m-d H:i:s');
    }
}

trait Identifiable {
    private string $id;
    
    public function generateId(): void {
        $this->id = uniqid('id_');
    }
    
    public function getId(): string {
        return $this->id;
    }
}

class Post {
    use Timestampable, Identifiable;
    
    public function __construct(public string $title) {
        $this->generateId();
    }
}

$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();

出力:

id_6789abc123 - 2024-01-15 10:30:00

Post class には、両方のトレイトのメソッドが追加されました。それぞれのトレイトは独自の機能を提供します。Timestampable は時間関連のメソッドを提供し、Identifiable は一意の ID を処理します。このアプローチにより、各トレイトが単一の責務に集中できるため、コードのモジュール性と再利用性が向上します。

2つのトレイトに同じ名前のmethodsがあるとどうなるでしょうか?それは競合する状況で、次のレッスンで詳しく学びます。

challenge icon

チャレンジ

簡単

複数のtraitを組み合わせて、productにpricingとinventoryの両方の機能を与えるproduct management systemを構築しましょう。各traitは単一の責任を担当し、あなたのproduct classは両方から機能を得ることになります。

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

  • Priceable.php:pricing機能を処理するPriceableというtraitを作成します。このtraitには次の要素を含めます。
    • private property $price(float)
    • priceを保存するmethod setPrice(float $price)
    • priceを返すmethod getPrice()
    • priceを小数点以下2桁で"$[price]"の形式に整形して返すmethod getFormattedPrice()
  • Stockable.php:inventoryを管理するStockableというtraitを作成します。このtraitには次の要素を含めます。
    • private property $stock(integer)
    • stockのquantityを保存するmethod setStock(int $quantity)
    • current stockを返すmethod getStock()
    • stockが0より大きい場合はtrue、otherwiseはfalseを返すmethod isInStock()
  • main.php:両方のtraitファイルを読み込み、PriceableStockableの両方のtraitを使用するProduct classを作成します。constructor promotionを使用してpublic $name propertyを定義します。constructorではpriceとstock quantityも受け取り、traitのmethodsを使ってそれらを設定します。

    3つの入力(product name、price、stock quantity)を受け取ります。これらの値でproductを作成し、4行をPrintします。

    • product name
    • formatted price(getFormattedPrice()を使用)
    • stock quantity
    • 在庫がある場合は"Available"、ない場合は"Out of stock"

これは、複数のtraitがどのように連携するかを示しています。あなたのProduct classは、一方のtraitからpricing capabilitiesを、もう一方のtraitからinventory managementを得ます。それぞれのconcernをきちんと分離しながら、それらを組み合わせてfully-featured productにしています。

自分で試してみよう

<?php
require_once 'Priceable.php';
require_once 'Stockable.php';

// TODO: Priceable と Stockable の両方のトレイトを使用する Product クラスを作成する
// public な $name プロパティにコンストラクタのプロモーションを使用する
// コンストラクタは name、price、stock を受け取り、トレイトのメソッドを使用して price と stock を設定する必要があります

class Product {
    // TODO: ここでトレイトを使用する

    // TODO: $name のコンストラクタプロモーションを使用してコンストラクタを実装する
    // そしてトレイトのメソッドを使用して price と stock を設定する
}

// 入力を読み取る
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));

// TODO: 入力値で Product インスタンスを作成する

// TODO: 製品名を出力する
// TODO: getFormattedPrice() を使用してフォーマットされた価格を出力する
// TODO: 在庫数量を出力する
// TODO: 在庫がある場合は "Available" を、ない場合は "Out of stock" を出力する
?>
quiz icon腕試し

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

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

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