支援対象地域:札幌、仙台、関東、愛知、関西、広島、福岡

  • TOP
  •   
  • コラム
  •   
  • 【Java】ポリモーフィズムとはこん

はじめに

本記事では、Javaのオブジェクト指向の上で重要となる、『ポリモーフィズム』について取り上げていきます。それではまずはじめに、オブジェクト指向について簡単に触れていきましょう。

オブジェクト指向とは?

「指向」とは、なにかをおこなう上での方向性などのことを意味し、また「オブジェクト(Object)」とは日本語に訳すと”物体””対象”を意味します。オブジェクト指向とは、ソースコードを書くうえで、ひとつひとつの要素を”物体”、より分かりやすく言うと”モノ”として捉え、プログラミングをおこなう方向性(考え方)を意味します。このオブジェクト指向には大きく分けて3つの要素である『継承』、『ポリモーフィズム』、『カプセル化』がありますが、3つの要素の中でも今回のキーワードである『ポリモーフィズム』についてが一番よく分からない、と感じてしまう方もいるのではないでしょうか。それでは以降より、ポリモーフィズムについて解説していきましょう。

ポリモーフィズムとは?

日本語では「多様性」「多態性」「多相性」などと呼ばれるこのポリモーフィズムですが、その考え方のベースイメージを簡単に言うと、物事を”ざっくり見てみましょう”という事です。例えば、ある一台の「タクシー」があるとして、この「タクシー」は、”ざっくり”見れば「車」で、もっとざっくり捉えていけば「乗り物」です。このように、何事ももとを辿ってざっくり捉た考え方をひとつ押さえておいてください。そのうえで、例えば様々な種類の乗り物(パトカーや自転車、飛行機など)が集結した場所があるとして、そこで司令塔(開発者)が「乗り物、動け!」と命令した時、その場所にいるすべての乗り物が各々の動作で動き、そして「車、動け!」と命令すれば、今度は車以外は動かず、”車”に属したものだけ(パトカーやタクシーなど)が各々の動作で動きます。このように、物事を大きな枠で捉えた上で、かつ一つの命令に対し各々が持った別の動きをすることができるのが、このポリモーフィズムの特徴です。

実際のコード例

それではここからは分かりやすくソースコードで見ていきましょう。今回の例えは、「楽器」です。まずは、ポリモーフィズムを活用していない方式でのソースコードです。

class Main {
	public static void main(String[] args) {
		//各楽器をそれぞれ生成
		Piano piano = new Piano();
		Guitar guitar =new Guitar();
		Drum drum = new Drum();

		//playとpauseメソッドを各楽器が順におこなう
		piano.play();
		piano.pause();

		guitar.play();
		guitar.pause();

		drum.play();
		drum.pause();
	}
}

//各楽器クラス
class Piano {
	void pause () {System.out.println("演奏を止める");}
	void play () {System.out.println("チャララーン");}
}
class Guitar {
	void pause () {System.out.println("演奏を止める");}
	void play () {System.out.println("ジャカジャーン");}
}
class Drum {
	void pause () {System.out.println("演奏を止める");}
	void play () {System.out.println("ドドドン");}
}

↓↓↓

=実行結果=
チャララーン
演奏を止める
ジャカジャーン
演奏を止める
ドドドン
演奏を止める

上では3つの楽器クラスを用意し、それぞれの楽器が音を鳴らした後演奏を止めるといった動作をおこなっています。ここで注目していただきたいのは、各楽器のメソッドには名前が同じメソッドであるpauseとplayメソッドがあり、pauseメソッドはまったく同じ内容、そしてplayメソッドは各々の音を奏でているため内容が違うという点です。ここではそれぞれに対して、「ピアノ、演奏して!」「ピアノ、止まって!」「ギター、演奏して!」・・・というように各楽器をひとつひとつの素材でしか捉えられていません。

ここでポリモーフィズムを活用し修正した例を実践していきます。上の状態からポリモーフィズム仕様に変更するには、オブジェクト指向の要素でもある『継承』を利用し、①各楽器を大きな括りでまとめる役の親クラス「楽器」をつくり、各楽器がそれを継承するようなかたちに変えてみます。そして、②親クラスである「楽器」クラスの持っている空のplayメソッドを、各楽器が自分仕様の動作にできるようにオーバーライド(上書きのようなもの)していきます。そして③楽器クラス型の配列(band)を作り、中身を各楽器のクラス型にしてインスタンスの生成します。(is-aの関係、つまり継承関係にあるインスタンスの生成は、可能となっています。)④その後、楽器クラス型の配列bandに対し、playとpauseを順番に行うよう命令します。

長々と説明しましたが、ポリモーフィズムにおいて一番関連深い作業は上の手順①②だと考えます。それでは、実際のコードは下の通りです。

class Main {
	public static void main(String[] args) {		
		//楽器クラス型の箱に、各楽器クラス型を詰めた配列
		Instrumental[] band = {new Piano(),new Guitar(),new Drum()};

		//拡張for文でplayとpauseメソッドを順に呼び出し
		for(Instrumental i : band) { 
		i.play();
		i.pause();
		}
	}
}

//楽器クラス
class Instrumental {
	void pause () {System.out.println("演奏を止める");}
	void play (){
		//何かしらの音で鳴る
	}
}

//楽器クラスを継承した各楽器クラス
class Piano extends Instrumental{
	void play () {System.out.println("チャララーン");}
}
class Guitar extends Instrumental{
	void play () {System.out.println("ジャカジャーン");}
}
class Drum extends Instrumental{
	void play () {System.out.println("ドドドン");}
}

↓↓↓

=実行結果=
チャララーン
演奏を止める
ジャカジャーン
演奏を止める
ドドドン
演奏を止める

無事、同じ結果を得る事ができました。このように、修正前は何事も各楽器ごとに捉えてしか命令できなかったものが、ある大きな括りを持たせ各々動作が違うところだけを上書きする事により、各々の根本として”楽器”である以上は持っていないといけない機能(今回はpauseとplay)をしっかり持ち、かつそれぞれの仕様で動作できる構成をつくることができるのが『ポリモーフィズム』です。今回の例は分かりやすい例えとして楽器を挙げましたが、より現実的なケースで言えば、ある機能のコードを書く上で、機能クラスの中にA.B.Cのメソッドがあるとし、またそれに並ぶ同類機能にもA.B.Cメソッドがあったとします。AとBは中身の動作も全く一緒、違うのはCだけ、という時に、今回の例と同じような捉え方でポリモーフィズムを適用する事で、よりシンプルに開発を進める事ができます。

ポリモーフィズムのメリット

代表的なのは下記2つです。

メリットその1.コードがきれいになる

同じ内容を持つクラスに何度も同じコードを書く必要がなくなるので、大きな規模の開発になるほど、無駄のないコードを書く事ができます。

メリットその2.重複したメソッドの変更にも柔軟に対応することができる

同じ内容を持つメソッドは親クラスから呼び出すため、変更がある場合も親クラスのメソッドを書き換えるだけでよくなり、柔軟な対応が可能になります。

おわりに

いかがでしたでしょうか。ポリモーフィズムを上手く使いこなせるだけで、その全体のコードを見た仕上がりを格段に変える事ができるはずです。他にも様々な活用例がありますが、本記事によってポリモーフィズムの考え方を知るきっかけとなっていただければ幸いです。最後まで読んでいただきありがとうございました。