Search

検索したいワードを入力してください

2019年03月13日

PHPでextendsとtraitを使ってメソッドを継承する

オブジェクト指向のプログラミング言語は、継承を利用することができます。そして、継承を利用することでコードの再利用や拡張、コードの保守性も向上します。PHPにも継承や関連する「extends」と「trait」があり、効率的な開発を行うことできます。

PHPでextendsとtraitを使ってメソッドを継承する

継承とは

継承とは、オブジェクト志向の概念の一つです。すでに存在しているオブジェクトをあるオブジェクトが引き継ぐことです。一般的に、引継ぎ元となっているオブジェクトを「親クラス」、「スーパークラス」などと言います。

また、引き継ぐ新しいオブジェクトを「子クラス」、「サブクラス」などと言います。プログラミング言語によって呼び名が変わりますが、考え方は同じです。

子クラスで親メソッドのメソッドを変更し異なる処理を行なう場合や子クラスだけに新しいメソッドを追加したりする場合に利用します。

もう少し分かりやすく具体的な例として、我々人間に例えると分かりすいです。人間の中には異なる言葉を話す人や様々な職業の方がいます。

プログラミングを行うプログラマーもその一つです。そして、仮に人間を親クラスとした場合、プログラマーは当然人間ですから人間から見るとプログラマーを子クラスと考えることができます。

簡単に一覧にすると、次のようになります。

[人間:親クラス]
・話す
[プログラマー:子クラス]
・システム開発について話す
・プログラミングする

プログラマーは、人間ですから話すことができますが、特にシステム開発について話すことができます。また、すべての人間がプログラミングができるわけではありませんが、プログラマーはプログラミングができます。

このように、基本的には親クラス(人間)の動作をするが、子クラスでは親クラスとは似ているけど少し違うことや新しいこともできます。これが継承です。

プログラミングの継承のメリット

では、プログラミングで継承を行うメリットは何でしょうか?継承のメリットは、「コードの再利用」と「拡張性」、そして「保守性」です。

プログラミングの継承のメリット1:コードの再利用ができる

まず、「コードの再利用」について、システム開発のプロジェクトを進めていくなかで同じようなクラスやメソッドを作成する機会が発生します。

作成するたびに同じコードを作成することは無駄です。その場合に、一部だけ異なるコードを作成する場合、すでに存在しているコードを継承して新しいコードを作成することで無駄なく効率的にプロジェクトを進めることができます。

プログラミングの継承のメリット2:コードの拡張性が上がる

次に、「拡張性」ですが、クラスを継承することで親クラスとほとんど同じだが、新しい処理も追加したい場合に、親クラスを継承することで子クラスで新しい処理のみ追加することでコードの機能を拡張します。それによって、無駄なコードの作成もなくなります。

プログラミングの継承のメリット3:保守性の向上

継承を利用することで「保守性の向上」という視点においてもメリットがあります。「保守性の向上」とは、すでに作成したコードの変更やメンテナンスが容易になることです。

プロジェクトが進む中で仕様の変更が発生することがあります。そのときに継承を利用していると変更対象の部分のみの変更で完了します。また、バグが発生した場合にもエラー箇所のみの修正で済みます。

継承は、コードをパーツ化するイメージに近いため保守性の向上という視点からも有効な手段となります。

継承は、オブジェクト指向の考え方がもとになっており、プログラミングの冗長性を省いたりシステム開発の効率化をはかることができます。

PHPでクラス継承を使う

ここまで、継承に関する基本的な考え方を紹介してきましたが、PHPにも継承が利用できます。具体的には、「extendsによるクラスの継承」と「traitによるコードの再利用」があり、順番に紹介します。

クラスを継承する

「クラスを継承する」とは、継承でも説明したとおり親クラスと子クラスが存在し、親クラスを子クラスが継承することです。

クラスの継承は、オブジェクト指向を採用しているPHPでも同じ考え方です。クラスの継承をすることで、親クラスのメソッドを利用が可能となり、子クラスのみで使用するメソッドを作成することができるようになります。

extendsとは

それでは、PHPのクラスの継承を具体的にどのように行うかを紹介します。PHPでは「extends」を使用してクラスの継承を行います。基本的なプログラム構造は次のとおりです。

【基本的な書き方】
class クラス名 extends 継承元クラス名 {
// ここにメソッドや処理を実装
}

「継承元クラス名」が親クラス、「クラス名」が子クラスに該当します。
子クラスでは、親クラスで実装されているメソッドを引き継ぎ利用することができます。

ただし、下記のサンプルコードのように、親クラスのメソッドを利用することができますが、親クラスのメソッドが「private」になっている場合は子クラスでも利用することができませんので注意が必要です。

【サンプルコード】
// 親クラス
class Parent {
public function sample () {
// このメソッドは子クラスでも利用できます
}
private function sample2 () {
// このメソッドは親クラスでも利用できません
}
}

extendsの使い方

「extends」をどのように使用するか実際のサンプルコードを使って紹介します。

【サンプルコード】
// 親クラスを定義
class Parent{
// 引数ありの食べるメソッドを作成
public function eatAct($str){
echo $str.'eatActメソッドが呼ばれました';
}
// 引数なしの話すメソッドを作成
public function speakAct(){
echo '親クラスのspeakActメソッドが呼ばれました';
}
}

//子クラスを定義
class Child extends Parent {
// 引数ありの食べるメソッドを作成
public function eatAct($str){
echo $str.'eatActメソッドが呼ばれました';
}
}

//インスタンスを生成
$parent = new Parent();
$child = new Child();

//食べるメソッドの呼び出し
$parent->eatAct('親クラスの');
$child->eatAct('子クラスの'); - ①
//話すメソッドの呼び出し
$parent->speakAct();
$child->speakAct(); - ②

【実行結果】
親クラスのeatActメソッドが呼ばれました
子クラスのeatActメソッドが呼ばれました
親クラスのspeakActメソッドが呼ばれました
親クラスのspeakActメソッドが呼ばれました

サンプルコードでは、PHPの親クラス・子クラスを定義し、親クラスにはeatAct,speakActメソッド、子クラスにはeatActメソッドのみ実装しています。

注目すべきところは、①では、子クラスのeatActメソッドを呼び出されています。eatActメソッドは子クラスにも実装されているため、子クラスのメソッドが優先されて呼び出されます。

また、②では、子クラスにspeakActメソッドが存在しないため親クラスのspeakActメソッドが呼び出されています。

継承の活用法

さらに、PHPのクラスの継承の活用法をサンプルコードを使って紹介します。

【サンプルコード】
// 親クラスを定義
class Parent{
// 食べるメソッドを作成
public function eatAct(){
echo 'eatActメソッド';
}
// 話すメソッドを作成
public function speakAct(){
echo 'speakActメソッド';
}
}

//子クラスを定義
class Child extends Parent {
// 文字列を出力するメソッド
public function printText($str1,$str2){
echo $str1.'と'.$str2;
}
}
// インスタンス生成
$child = new Child();

$str1 = $child->eatAct(); - ①
$str2 = $child->speakAct(); - ②
$child->printText($str1,$str2);

【出力結果】
eatActメソッドとspeakActメソッド

サンプルコードの①と②は、PHPの親クラスで定義されたメソッドを呼び出しています。子クラスでは、文字列を出力するメソッドのみ実装しています。

このように継承することで、子クラスのメソッドの変更やメンテナンスを行いやすくなるため保守性の向上が見込めます。

traitでコードを再利用する

次に、PHPの継承で使用される「traitによるコードの再利用」について紹介します。

traitとは

PHPの「trait」は、継承することなくメソッドやメンバを再利用できます。また、「trait」は、PHPのバージョン5.4.0以降で使用できます。

基本的なプログラム構造は次のとおりです。

【基本的な書き方】
trait トレイト名{
処理
}
class クラス名{
use トレイト名
}

traitで処理を定義します。処理部分には、メソッド・static変数・プロパティを実装できます。そして、使用したいクラスで「use」を使ってtraitを指定します。

また、1つのクラスで複数のtraitを使用したい場合には、「use trait1,trait2」のようにカンマで区切って使用することができます。

traitの使い方

それでは、PHPのtraitの使い方をサンプルコードで紹介します。

【サンプルコード】
// traitのParent1を定義
trait Parent1{
function eatAct(){
echo 'eatActメソッド';
}
}
// traitのParent2を定義
trait Parent2{
function speakAct(){
echo 'speakActメソッド';
}
}

//子クラスを定義
class Child {
//useで使用するtraitを指定する
use Parent1, Parent2; - ①

public function walkAct($str){
echo 'walkActメソッド';
}
}

//インスタンスの生成
$child = new Child();

//メソッドの呼出し
$child->eatAct();
$child->speakAct();
$child->walkAct();

【出力結果】
eatActメソッド
speakActメソッド
walkActメソッド

サンプルコードの①で使用するtraitを指定することで、traitに定義されているメソッドを使用することが可能となります。PHPのtraitについては、指定することでコードの再利用が可能となります。

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

「オーバーライドの優先順位」とは、継承した親クラスのメソッドとtraitで定義したメソッドが同じメソッド名の場合に、どちらが優先するかということです。次のサンプルコードをご覧ください。

【サンプルコード】
class Parent{
public function eatAct(){
echo '継承:eatActメソッド';
}
}
trait Parent1{
public function eatAct(){
echo 'trait:eatActメソッド';
}
}
class Child extends Parent {
use Parent1;
}

$child = new Child();
$child->eatAct();

【出力結果】
trait:eatActメソッド

サンプルコードでは、継承元のParentクラスに定義されているeatActメソッドとtraitで定義されているeatActメソッドは同じ名ですのでどちらが優先されるか問題になります。
結論としては、出力結果のとおり「traitで定義したメソッドが優先」されます。

衝突の解決方法

最後に、PHPのtrait同士で同じ名のメソッドがあり使用する場合に「衝突」が発生しますので、その場合の解決方法を紹介します。

【サンプルコード】
// traitのParent1を定義
trait Parent1{
function eatAct(){
echo 'Parent1:eatActメソッド';
}
}
// traitのParent2を定義
trait Parent2{
function eatAct(){
echo 'Parent2:eatActメソッド';
}
}

//子クラスを定義
class Child {
//useで使用するtraitを指定する
use Parent1, Parent2;
}

$child = new Child();
$child->eatAct(); - ①

サンプルコードの①でメソッドの呼び出しを行なっていますが、Parent1, Parent2のどちらのeatActメソッドが優先するかということです。結論としては、優劣がつかないため「エラー」となります。

エラーの解決方法として、PHPの「insteadof」を使用することで利用するメソッドを明示的に指定します。

【基本的な使い方】
使用するトレイト名::メソッド名 insteadof 使用されないトレイト名


先ほどのサンプルコードに「insteadof」に利用すると下記のとおりです。

【サンプルコード】
// traitのParent1を定義
trait Parent1{
function eatAct(){
echo 'Parent1:eatActメソッド';
}
}
// traitのParent2を定義
trait Parent2{
function eatAct(){
echo 'Parent2:eatActメソッド';
}
}

//子クラスを定義
class Child {
//useで使用するtraitを指定する
use Parent1, Parent2;
Parent2::workItem insteadof Parent1; - ①
}

$child = new Child();
$child->eatAct();


【出力結果】
Parent2:eatActメソッド

サンプルコードの①で優先したいtraitを指定することでエラーの発生を回避することができます。

継承をマスターして効率的にPHPプログラミングをしよう

いかがだったでしょうか?
継承を使えば効率的に開発をすることができます。アプリケーションを作るときには必ず使うものなので、しっかりと勉強しておきましょう。

多くの人がプログラミングを諦めてしまう理由をご存知ですか?



近年プログラミングを勉強する人が増えています。

プログラミング学習者の多くは独学から取り組もうとしますが、だいたい80%ほどは3ヶ月も続かずに諦めてしまいます。早い人は1日目で。

多くの人がプログラミングを独学しようとして諦める理由は、次の3つ。
●モチベーションが維持できない
●エラーの原因・解決方法が分からない
●どう学習すればよいか分からない

TechBoostというプログラミングスクールでは、みんなと一緒にプログラミングをするのでモチベーションの維持ができ、分からないことがあればマンツーマンで教えてくれ、徹底的に研究された初心者向けの教材が揃っています。

TechBoostを卒業後、実際にエンジニアとして転職した方もいるほど。

本気でプログラミングを学びたい方は、一度無料のカウンセリングでご相談ください。プログラミングを嫌いになる前に。

tech boost卒業生インタビュー

tech boostの卒業生の声を聞きました。あなたがプログラミングを学びたい理由を、一度考えてみてください。
営業→Javaエンジニア→Rubyエンジニアと転向し、第一志望のFinTech企業で働く山下さん
元営業、ビジネスのわかるエンジニアを目指す菅原さん
サンフランシスコに交換留学し、シリコンバレーのVCでインターン中の梅本さん
予備校の営業から半年でエンジニア転職を果たした小田島さん

tech boostの口コミ



Related