トレイト
私の PHP 開発者の友人の多くは、PHP 5.4.0 で導入された新しい概念であるトレイトについてあまり知りません。トレイトはインターフェイスのように見えますが、クラスのように機能します。では、トレイトは正確には何でしょうか?どちらでもありません。
トレイトには、1 つ以上の実際の PHP クラスに埋め込むことができる部分的な実装 (定数、プロパティ、メソッドなど) があります。トレイトには 2 つの役割があります。1 つはクラスが実行できることを示すこと (インターフェイスと同様)、もう 1 つはモジュール実装を提供すること (クラスと同様) です。
あなたはすでに他の言語の特徴についてある程度理解しているかもしれません。たとえば、Ruby のモジュールとミックスインの機能は、PHP の特性と非常に似ています。
なぜ特性を使用する必要があるのか
PHP言語は古典的な継承モデルを使用します。これは、基本的な実装を提供する共通のルート クラスから始めることを意味します。ルート クラスから、親クラスのさまざまな実装を直接継承する、より具体的なクラスが作成されます。これは継承階層と呼ばれ、多くのプログラミング言語がこの共通のパターンを使用します。
わかりやすくするために、生物学を勉強するために高校にタイムスリップしたと想像してください。研究した生物の門、目、科、属、種をまだ覚えていますか?合計 6 つの主要な領域があり、領域はドアから派生し、門は階級から派生し、階級は目から派生し、目は科から派生し、科は属から派生します。属の後に種が続きます。種の階層の下にあるそれぞれの降下は、特定の特性を表します。
古典的な継承モデルは、ほとんどの場合にうまく機能します。しかし、同様の動作を実装する必要がある無関係なクラスが 2 つある場合はどうなるでしょうか?たとえば、ある PHP クラスは RetailStore と呼ばれ、別の PHP クラスは Car と呼ばれ、これらはまったく無関係な 2 つのクラスであると言え、継承関係の観点から共通の親クラスを共有することはできません。ただし、どちらのクラスでも、地図座標を表示するには地理的位置の経度と緯度が必要です。
私たちはこの問題を解決するためにトレイトを作成しました。無関係なクラスに部分的な実装を注入することができます。特性により、コードの再利用も容易になります。
この問題に遭遇したとき、私の最初の解決策 (そして最悪の解決策) は、RetailStore クラスと Car クラスが継承するパブリック親クラス Geocodable を作成することです。この解決策は非常に良くありません。無関係な 2 つのクラスに共通の祖先を共有させることは、それぞれの継承階層において非常に厄介に見えるからです。
私の 2 番目の解決策 (少し良い) は、地理位置情報の実装に必要なメソッドを定義する Geocodable インターフェイスを作成することです。 RetialStore クラスと Car クラスは両方とも、この Geocodable インターフェイスを実装できます。これは、各クラスがその自然な継承関係を保持できるようにするための、確かに優れたソリューションです。ただし、依然として各クラスのインターフェイスで定義を繰り返す必要があり、これは DRY ソリューションではありません。
DRYとは、Do notrepeat Yourselfの略です。プログラミングの良い習慣として、同じコードを複数の場所で決して繰り返さないでください。 1 つのコードを変更したからといって、他の場所で同じコードを受動的に変更しなければならないという状況は起こり得ません。
私の 3 番目の解決策 (最良の解決策) は、Geocodable 特性を構築し、それに関連するメソッドを定義して実装することです。クラス継承階層を中断することなく、Geocodable 特性を RetailStore クラスと Car クラスに追加できます。
特性を構築する方法
以下は、PHP 特性を定義する方法を示しています:
<?php trait MyTrait { // 此处是trait的具体实现 }
特性の使用法をよりわかりやすく示すために、ジオコーディング可能な例に戻りましょう。 RetailStore クラスと Car クラスが地理的測位機能をサポートする必要があることは誰もが知っており、継承とインターフェイスが最適なソリューションではないことに誰もが同意するでしょう。代わりに、地図上にマークできる経度と緯度の座標を返す Geocodable 特性を構築します。例 2-12 は、完全な Geocodable 特性を示しています。
例 2-12 Geocodable trait の定義
<span style="font-size:14px;"><?php trait Geocodable { /** @var string */ protected $address; /** @var \Geocoder\Geocoder */ protected $geocoder; /** @var \Geocoder\Result\Geocoded */ protected $geocoderResult; public function setGeocoder(\Geocoder\GeocoderInterface $geocoder) { $this->geocoder = $geocoder; } public function setAddress($address) { $this->address = $address; } public function getLatitude() { if (isset($this->geocoderResult) === false) { $this->geocodeAddress(); } return $this->geocoderResult->getLatitude(); } public function getLongitude() { if (isset($this->geocoderResult) === false) { $this->geocodeAddress(); } return $this->geocoderResult->getLongitude(); } protected function geocodeAddress() { $this->geocoderResult = $this->geocoder->geocode($this->address); return true; } }</span>
Geocodable 特性は 3 つのクラスのプロパティを定義します:
続きます...
以上、[モダンPHP]第2章の新機能3つの特徴を内容も含めて紹介しましたが、PHPチュートリアルに興味のある友人の参考になれば幸いです。