複数のトレイトの使用
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:00Post class には、両方のトレイトのメソッドが追加されました。それぞれのトレイトは独自の機能を提供します。Timestampable は時間関連のメソッドを提供し、Identifiable は一意の ID を処理します。このアプローチにより、各トレイトが単一の責務に集中できるため、コードのモジュール性と再利用性が向上します。
2つのトレイトに同じ名前のmethodsがあるとどうなるでしょうか?それは競合する状況で、次のレッスンで詳しく学びます。
チャレンジ
簡単複数の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]"の形式に整形して返すmethodgetFormattedPrice()
- private property
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を返すmethodisInStock()
- private property
main.php:両方のtraitファイルを読み込み、PriceableとStockableの両方のtraitを使用するProductclassを作成します。constructor promotionを使用してpublic$namepropertyを定義します。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" を出力する
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: PHPオンラインコンパイラ