検索

キーワード


【Java】 オブジェクト指向の主要素「ポリモーフィズム」とは?

  • 公開日:2020-10-20 11:07:57
  • 最終更新日:2021-01-26 09:31:39
【Java】 オブジェクト指向の主要素「ポリモーフィズム」とは?

こんにちは、駆け出しプログラマーの若江です!

ここでは初学者として学習を終えた私からアウトプットの意味も込めて、

ポリモーフィズムについて紹介させていただきます。

できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!


関連記事リンク:オブジェクト指向の継承の紹介 / 拡張for文の紹介 / 抽象クラスの紹介 / インターフェースの紹介 / オーバーライドの紹介 / オーバーロードの紹介 / インスタンスの紹介 / 配列の紹介 / 変数の紹介

ポリモーフィズム(オブジェクト指向)の考え方

Java のオブジェクト指向の概念を支える要素には「独立性」「再利用性」「拡張性」の3つがあります。

この中で3つ目の性質「拡張性」を実現しているのがポリモーフィズムの考え方です。

ポリモーフィズムは「再利用性」とも深い関わりを持つため、

再利用性を実現する「継承」を理解してからこの記事を読んでいただくとより理解が深まると思います。

ここではオブジェクト指向のポリモーフィズムに焦点を当てて紹介させていただきます。


ポリモーフィズムの概念

ポリモーフィズムの考え方は、広い枠組みでモノを扱うことで、高い「拡張性」を持たせると言うものです。

拡張性とは、1つのモノを起点にして機能を派生させられる性質のことを指します。

例えば、リンゴを起点にすると「青リンゴ」「アップルパイ」などへ派生させることができます。

この派生する性質が拡張性です。


ポリモーフィズムの目的

ポリモーフィズムは「多様性」や「多態性」と言う意味で、

オブジェクトの拡張性を適切に高める(機能の派生幅を広げる)ことで、

より柔軟なオブジェクトの扱い方ができるようになることを目指します。


先ほどの例でいうと、「リンゴ」の派生幅はリンゴにまつわるモノへの派生しかできず拡張性は低いと言えます。

ポリモーフィズムの考え方では、このリンゴオブジェクトの拡張性を高めることで、

オブジェクトの扱いをより柔軟性の高いものにすることを目的にしています。


ポリモーフィズムによって柔軟性を高める方法は、

オブジェクトの捉え方をより抽象的にすることで実現させます。

言い換えるとオブジェクトを広い枠組みで捉えてカテゴリー分けするようなイメージです。

例えば、リンゴオブジェクトを抽象的に捉えると「果物」にカテゴリー分けすることができます。

果物オブジェクトはリンゴオブジェクトよりも拡張性が高いため、

「バナナ」や「オレンジ」「キウイ」など様々なモノを扱うことができます。


果物オブジェクトのように、オブジェクトを抽象化することで拡張性を高めます。

拡張性を高めることでプログラマーの負担を減らし、変更に強いプログラムを作成でき、

プログラム全体を見やすくすることができます。


ただし拡張幅の必要度は状況によって変化します。

例えば、青果店では幅広く果物を取り扱うため果物オブジェクトが適切ですが、

リンゴを使ったレシピをまとめたレシピ本には、果物オブジェクトは不要です。

そのため拡張すればオブジェクト指向のプログラミングができるというものではありません。



ポリモーフィズムの実現方法

Java  ではポリモーフィズムをクラスの継承やインターフェースの実装で実現させます。

具体的にはインスタンス生成時に扱う型をスーパークラスやインターフェースの型にすることで拡張性を高めます。


サンプルコードで確認してみましょう。

◆ポリモーフィズムの例

【Fruitsインターフェース】

public interface Fruits {
}

【Appleクラス】 Fruits インターフェースを実装したクラス

public class Apple implements Fruits{
}

【Orengeクラス】 Fruits インターフェースを実装したクラス

public class Orenge implements Fruits{
}

【実行クラス】 Fruits 型の変数に Apple インスタンスを代入、その後 Orenge インスタンスを再代入

public class Test {
	public static void main(String[] args) {

		Fruits fruit = new Apple(); // Fruits 型変数に Apple インスタンスを代入
		fruit = new Orenge(); // fruit に Orenge インスタンスを代入
	}
}


Fruits インターフェースを実装したクラスは、インスタンス生成時に Fruits を型として扱えます。

こうすることで、Apple インスタンスを扱っていたところ急遽 Orenge インスタンスへ変更することになっても、

Fruits インターフェースの型を持つインスタンスは対応することができます。


このように機能を拡張させることができるのは継承関係が存在するためです。

そのためオブジェクト指向の要素である「継承」と「ポリモーフィズム」は深く関わり合っていると言えます。


オーバーライドとオーバーロード

クラスの拡張性が高くなったということは、派生した各クラスの振る舞いも当然変わります。

継承により派生したクラスの振る舞いを変える方法は、

新たなメソッドを追加するか、オーバーライドオーバーロードで振る舞いを変えることができます。


・オーバーライドは親クラスの持つメソッドを機能拡張して動作させることができるため

 ポリモーフィズムの考えに則しています。

・オーバーロードは自クラスのメソッドで受け取るデータに違いよって機能を拡張させているため

 ポリモーフィズムの考えに則しています。



継承を紹介させていただいた記事でも取り上げましたが、

カメラオブジェクトの「撮影をする」メソッドをオーバーライドすることで、

「写真を撮影する」や「動画を撮影する」と言ったように機能を拡張することができます。

また「写真を撮影する」機能をオーバーロードすることで、

「夜景モードで写真を撮る」や「ポートレートで写真を撮る」と言った処理に派生させることもできます。


◆オーバーライドとオーバーロードでの拡張の例

【カメラクラス】

public class Camera {

	// 抽象的に「撮影をする」メソッド作成
	public void snap() {
		System.out.println("撮影する");
	}
}

【子クラス】 カメラクラスを継承してメソッドをオーバーライド・オーバーロード

public class Camera2 extends Camera {

	// Camera クラスの snap メソッドをオーバーライド
	public void snap() {
		System.out.println("写真を撮る");
	}

	// 自クラスの snap メソッドをオーバーロードして夜景撮影モード作成
	public void snap(int num) {
		System.out.println("シャッタースピード" + num + "で撮影");
	}

	// 自クラスの snap メソッドをオーバーロードしてポートレートモード作成
	public void snap(int num, int distance) {
		System.out.println("ズーム率" + num + "%" + "被写体との距離" + distance + "m");
	}
}


このようにオーバーライドやオーバーロードをすることで、

クラス特有の振る舞いを持たせることができるため拡張性を高めることができます。



ポリモーフィズムの利用

ポリモーフィズムはオブジェクト指向の「拡張性」を実現するための要素であることを紹介しました。

ポリモーフィズムを活用すればスーパークラスやインターフェースの型で抽象化したオブジェクトから、

1つのメソッドを呼び出すだけで複数の異なる結果を返すこともできます。


例えば親クラスにメソッドを作成して各子クラスでオーバーライドし、それぞれの処理を記述します。

親クラス型の配列インスタンスに子クラスのインスタンスを保持させて、

拡張for文を使いオーバーライドで使用したメソッドを呼び出すと、

1つのメソッドで子クラスそれぞれの結果を返します。


◆1つのメソッドで複数の結果を返す例

【親クラス】

public class Fruits {

	public void name() {
	}
}

【子クラス①】 Fruits クラスを継承して name メソッドをオーバーライド

public class Apple extends Fruits{

	public void name() {
		System.out.println("リンゴ");
	}
}

【子クラス②】 Fruits クラスを継承して name メソッドをオーバーライド

public class Orenge extends Fruits{

	public void name() {
		System.out.println("オレンジ");
	}
}

【実行クラス】  Fruits 型の配列インスタンスで name メソッドを呼び出し

public class Test {
	public static void main(String[] args) {

		Fruits[] fruits = {new Apple(), new Orenge()};
		for(Fruits fruit : fruits) {
			fruit.name();
		}
	}
}


Apple クラスも Orange クラスも Fruits クラスからオーバーライドした name メソッドを持っているため、

Fruits クラスの name メソッドを呼び出せば「リンゴ」と「オレンジ」を表示させることができます。

もしポリモーフィズムの考え方を知らなければ、リンゴ型のインスタンスとオレンジ型のインスタンスを作成し、

それぞれの名前をそれぞれのインスタンスで呼び出すことになります。


簡単な例題のためプログラミングの負担やプログラムの見やすさの差は少ないですが、

大きなプロジェクトになるほどその差は広がります。

そのため Java での開発は当然オブジェクト指向に沿ってプログラムされており、

Java での開発には必須の概念となっています。



まとめ

ポリモーフィズムはクラスやメソッドが再利用されることを前提としています。

Java の基礎を学習する上でポリモーフィズムを理解していると、

継承やオーバーライド、オーバーロード、インターフェース、抽象クラスなどの理解がしやすくなります。

ポリモーフィズムは耳慣れない少し難しい概念ですがしっかり押さえておきましょう。


関連記事リンク

オブジェクト指向の継承の紹介 / 拡張for文の紹介 / 抽象クラスの紹介 / インターフェースの紹介 / オーバーライドの紹介 / オーバーロードの紹介 / インスタンスの紹介 / 配列の紹介 変数の紹介



【著者】

若江

30代で異業種となるIT業界へ転職した駆け出しのプログラマです。これまで主に Java や Ruby、HTML/CSS を使って学習を目的としたショップサイトや掲示板サイトの作成を行いました。プログラマとしての経験が浅いからこそ、未経験者の目線に近い形で基礎の紹介をしていきたいと思います。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様