【PHP入門】継承(extends)、トレイト(trait)を使いこなそう!

PHPではクラスを継承したり、トレイトを使用することで、自クラス以外のメンバを引き継ぐことできます。

この記事では、クラスを継承するextendsやコードを再利用するtraitについて、以下の内容で解説していきます。

  • extendsの使い方
  • traitの使い方
  • extendsとtraitの優先順位
  • traitにおける衝突の解決方法

今回はそんな継承(extends)、トレイト(trait)について、わかりやすく解説します!

クラスを継承する

ここでは、extendsを使用してクラスを継承する方法を紹介します。

extendsとは

クラスのメンバを他のクラスで継承したい場合にextendsを使用します。extendsを使用すればクラスを拡張することが可能で、サブクラスは親クラスからメソッドの内容を引き継ぐことができます。

extendsを使用した継承は、以下のように記述します。

書き方:

extendsはクラスを宣言する時に、クラス名の後に「extends 継承元クラス名」で継承元である親クラスを指定します。このようにクラスを定義すると、そのクラスは継承元のクラスのメンバを引き継ぐことができます。

しかし、親クラスでprivate修飾子による権限が指定されている場合は、そのメンバを引き継ぐことはできませんので注意しましょう。

extendsの使い方

extendsを使用し、クラスを継承するサンプルです。

サンプルプログラム:

実行結果:

サンプルでは親クラスであるParentClassと、extendsで親クラスを継承した子クラスであるChildClassを定義しています。実行結果のとおり、クラスの継承を行えば子クラスであるChildClassのインスタンスから親クラスのメソッドにアクセスすることができます。

また、ChildClassのインスタンスから親と子クラスの両方に存在するメソッドであるworkItem1にアクセスした場合、子クラスのメソッドが優先されます。

継承を使用した活用法

継承を活用すれば、親クラスの処理内容を子クラスで引き継いで処理を継続することが可能です。

以下は、親クラスの2つのメソッドで配列のキーと値をそれぞれ生成し、子クラスで親クラスを継承して配列を結合するサンプルです。

サンプルプログラム:

実行結果:

サンプルでは、親クラスであるFruitsClassの2つのメソッドでキー用の配列と値用の配列を生成しています。次に子クラスであるCombClassのメソッドで、親クラスで生成した2つの配列をarray_combine関数を使用して結合しています。

extendsによる継承を行えば、このように親クラスの処理を引き継げるので、各処理ごとにわかりやすく記述することができます。

サンプルで使用したarray_combine関数については、以下の記事で詳しく解説しています!

【PHP入門】配列を結合するさまざまな方法まとめ!
更新日 : 2017年9月3日

トレイトでコードを再利用する

ここでは、traitを使用してコードを再利用する方法を紹介します。

traitとは

PHPのバージョン5.4.0以降では「trait(トレイト)」と呼ばれるコードを再利用するための機能が導入されました。トレイトは継承することなくメンバを他のクラスで使用することができます。

PHPではクラスを多重継承することができませんでしたが、traitにより多重継承と同様なことができるようになりました。

トレイトは以下のように記述します。

書き方:

トレイトは「trait トレイト名」で宣言します。トレイトにはメソッドやプロパティ、staticメンバを定義できます。

トレイトを利用するクラスはuseキーワードでトレイト名を指定します。一つのクラスから複数のトレイトを使用する場合は、トレイト名をカンマ区切りで指定します。

トレイトの使い方

トレイトを使用してコードを再利用するサンプルです。

サンプルプログラム:

実行結果:

サンプルでは、トレイトであるTrait1とTrait2を定義し、それらを利用するクラスであるChildClassを定義しています。ChildClassでuseキーワードで使用するトレイトを指定しておけば、extendsと同様にトレイトのメンバを引き継ぐことができます。

実行結果のとおり、ChildClassクラスのインスタンスから2つのトレイトのメンバが参照できていることがわかりますね!

オーバーライドの優先順位

あるクラスが継承とトレイトを同時に使い、親クラスとトレイトに同名のメンバがあった場合、どちらが優先されるのでしょうか。

次のサンプルプログラムで確認してみます。

サンプルプログラム:

実行結果:

クラスChildClassは、ParentClassを継承し、Trait1を利用します。

ParentClassにもTrait1にもworkItemメソッドが存在しますが、ChildClassのworkItemメソッドを実行するとTrait1の「Processing of Trait」が表示されます。継承したメンバよりトレイトで追加したメンバの方が優先されます。

衝突の解決方法

あるクラスが複数のトレイトを利用し、それらのトレイトに同名のメンバがあった場合はどうなるでしょうか?

次のサンプルプログラムで確認してみます。

サンプルプログラム:

クラスChildClassはTrait1とTrait2を利用しますが、どちらのトレイトにもworkItemメソッドが存在します。

このプログラムを実行すると、以下のようなエラーが発生します。

実行結果(ログ):

このような名前の衝突を解決するには、insteadof演算子を使ってどちらを使用するか定義しておく必要があります。

「use トレイト名1, トレイト名2」の後をブロックで囲み、そのブロック内に以下のように記述します。

書き方:

Trait2のworkItemメソッドが使用されるように修正してみます。

サンプルプログラム修正:

実行結果:

「Trait2::workItem insteadof Trait1;」でTrait2のworkItemメソッドが使用され、「Processing of Trait2」が表示されます。

まとめ

今回は継承(extends)、トレイト(trait)について解説しました。継承やトレイトを使いこなすことで、同じコードを書かず開発効率が上がり、わかりやすいコーディングができるようになります。

継承(extends)、トレイト(trait)について忘れてしまったら、この記事を思い出してくださいね。

現役フリーランスエンジニアによる無料体験レッスン実施中!

もし、あなたが、

  • 経験、年齢、学歴に不安がある
  • 挫折しない学習方法が知りたい
  • アプリ開発で困っている
  • エンジニアの”生”の声が聞きたい!
  • 仕事獲得の仕方がわからない
  • エンジニアに転職したいが何をすればいいかわからない

など、プログラミング学習やキャリアのことでお困りであれば、まずは『無料体験レッスン』にお申し込み下さい。

あなたにとって、最適の解決策をご提案させていただきます。

詳しくは下の画像から詳しいサービス内容をご確認ください。

cta_mtm3

LINEで送る
Pocket

書いた人

ヤマシタ

フリーランスエンジニア。ITに関わるさまざまなコンテンツの企画・制作も行っています。
ITに関してはノウハウ系、ライフハック系、トレンド系など、今まで200本以上の執筆経験があります

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説