まえがき
みなさんはプリキュアは好きですか?
私?えぇもちろん大好きですよ。
好きなプリキュアはキュアミューズ、キュアハート、キュアエール、キュアミルキーです。
まぁそんな事は置いといてですね?
ある日思ったんですよ。
「プリキュアってポリモーフィズムの説明に使えるくない?」って
なので今回はそんな記事です。
前提環境
これから登場するお話は全て以下の環境を前提に書いています。
OS: Windows 10 20H2(19042)
Java: OpenJDK 16
開発環境: Eclipse 2021-03
まぁJavaなのでOSとか開発環境とか特に気にしなくても大丈夫ですよ。Javaのバージョンさえ合わせていればね。
Javaのバージョンも8くらいからなら動きます(多分)
1.ポリモーフィズムとは?
この記事執筆時点でのWikipediaには以下のように記されています。
プログラミング言語の各要素(定数、変数、式、オブジェクト、関数、メソッドなど)についてそれらが複数の型に属することを許すという性質を指す。ポリモルフィズム、多態性、多相性、多様性とも呼ばれる。対義語はモノモーフィズム (Monomorphism)、単態性、単相性で、プログラミング言語の各要素が唯一つの型に属するという性質を指す。
はて?何を言ってるのかさっぱりわからん。
まぁ筆者がそんな事を言ってたらこの記事が成り立たないのでそんなことは無いです。
つまりですね?
インスタンス(クラスをnewしたもの)をインスタンスの型の他、様々な型の中に入れることができる!ってこと。
StringクラスのインスタンスはObjectの型の中に入れる事ができる!
Object a = "aaa";
StringクラスのインスタンスはCharSequenceの型の中に入れる事ができる!
CharSequence b = "bbb";
なぜこんな事ができるのか?
Stringクラスのjavadoc(Javaのドキュメント)にはこう書かれています。
クラスString
java.lang.Object
java.lang.String
すべての実装されたインタフェース:
Serializable, CharSequence, Comparable<String>
つまりこれは、Stringクラスは
Objectを継承してて、
Serializableと、CharSequenceと、Comparableってインタフェースを実装している
って事。
インスタンスは継承してたり、実装されてたりしたクラス、インタフェースを型にしてインスタンスを代入することができる!
なのでObjectに入れる事ができるんですね~~~
補足
データ型が親クラスのだったりするとそのクラスで初めて書かれたメソッドやフィールドを呼び出す事ができません。
つまり、Objectに入れたStringのインスタンスはStringクラスのメソッドを呼び出せないということです。
Object a = "abc";
a.substring(0,2);//これは無理!
じゃぁどうすれば良いのか
答えは「キャスト」するんです!
Object a = "abc";
((String)a).substring(0,2);//OK
こんなふうに、変数の前に括弧でStringって書ことをキャストって言います。
それで、(String)aをもう一つ括弧で囲ってあげると、「((String)a)」これ自体がStringになるので、
これに対してsubstring()というStringクラスのメソッドが実行できるようになるわけですね~
本題
話がダイブそれてしましました…
さて、プリキュアの話に戻りましょう。
1番可愛いプリキュアがキュアミューズな事は周知の事実なのですが、今回は最新のプリキュア、トロピカルージュプリキュアでやりましょう。
まずポリモーフィズムでは上の項目で話した通り、親クラスや実装しているインタフェースが必要です。
そこで今回はインタフェース「Precure」を作って各プリキュアクラスに実装しましょう。
サンプルなのであまり複雑にならないようにメソッドを2つだけにします。
//Precure.java
package com.sakurai_shinya.precure_polymorphism;
public interface Precure {
void transform();
void lastAttack();
}
はい、これで実装するインタフェースが完成しました。
次にトロピカルージュプリキュアの4人を作っていきましょう
//CureSummer.java
package com.sakurai_shinya.precure_polymorphism;
public class CureSummer implements Precure {
@Override
public void transform() {
System.out.println("ときめく常夏!キュアサマー!");
}
@Override
public void lastAttack() {
System.out.println("プリキュア!おてんとサマーストライク!");
System.out.println("ビクトリー!");
}
}
他3人は省略してメソッドの部分のみを記載します。
//CureCoral.java
@Override
public void transform() {
System.out.println("きらめく宝石!キュアコーラル!");
}
@Override
public void lastAttack() {
System.out.println("プリキュア!もこもこコーラルディフュージョン");
System.out.println("ビクトリー!");
}
//CurePapaya.java
@Override
public void transform() {
System.out.println("ひらめく果実!キュアパパイヤ!");
}
@Override
public void lastAttack() {
System.out.println("プリキュア!ぱんぱかパパイアショット!");
System.out.println("ビクトリー!");
}
//CureFlamingo.java
@Override
public void transform() {
System.out.println("はためく翼!キュアフラミンゴ!");
}
@Override
public void lastAttack() {
System.out.println("プリキュア!ぶっとびフラミンゴスマッシュ!");
System.out.println("ビクトリー!");
}
それでは今回起動するプログラムを書いていきます。
//Main.java
package com.sakurai_shinya.precure_polymorphism;
public class Main {
public static void main(String[] args) {
// インスタンス作成
Precure precure = new CureSummer();
// 変身
precure.transform();
// 極め技
precure.lastAttack();
}
}
さて、ここまで書けたらぜひ実行してみてください。
ときめく常夏!キュアサマー!
プリキュア!おてんとサマーストライク!
ビクトリー!
こんなように出力されれば成功です!
次にMainクラスの「//インスタンス作成」って書いてある行の
newの後ろのクラス名の部分だけを別のプリキュアクラスに変更して実行してみてください。
Precure precure = new CureCoral(); //CureSummer → CureCoral
さて、どうなるでしょうか。
きらめく宝石!キュアコーラル!
プリキュア!もこもこコーラルディフュージョン
ビクトリー!
こんなように出力されれば成功です!
さて、ここまで来て理解できればこの記事を私が書いたのにも意味があったというものですよ。
ここで気づいて欲しいのは、
**「インスタンスが変わると挙動が変わる」**ということ。
new の後ろのクラス名を変えるということはインスタンスを変えているということです。
「インスタンスが変わると」ってところが大事なんですよ。
例えばifとかswitchで結果的な挙動が変わってるという事ではポリモーフィズムとは言えません。
このポリモーフィズムを応用すると、引数としてインスタンスを渡すと処理が変わるメソッドなんてのも作れるようになります。
(マルチスレッドプログラミングを行う時に使うThreadクラスとRunnableインタフェースもその例ですね)
最後に
プリキュアは良いぞ。