こんにちは、コイキングです。
本記事では OOP(Object Oriented Programming == オブジェクト指向プログラミング)の説明のうち、ポリモーフィズムについて、説明したいと思います。
1. ポリモーフィズムとは?
一つの機能が状況によって、違う結果を出す事で、
Javaでは'親クラス'又は'インターフェース'を定義し、親を継承した子クラスで親の機能を再定義して**親クラスの参照変数から子クラスのインスタンスを参照し、**親クラスの参照変数から子クラスごとに再定義されたメソッドを呼び出すこととするのを言います。
1) ポリモーフィズムの長所
- 多種多様なインスタンスを一つの親の参照変数にて管理できるため、コードの量が減り、コードの維持保守がより楽になります。
- 一つの親を共有する子クラスを増やし機能を再定義することで新機能の追加が可能がため、拡張に有利で、結合度が強くならないようにコードの実装ができます。
2) ポリモーフィズムの短所
- ちゃんと活用するのは難しいため、プログラマーの能力によりコードの品質が違くなる。
※ 例示コード
package objective.basic05;
import objective.basic04.Animal;
public class Cat extends Animal {
protected String breed;
protected String cryingSound = "Niya~!";
public Cat(String name, int age, String breed) {
super(name, age);
this.breed = breed;
}
public void crying() {
System.out.println(this.cryingSound);
}
public void crying(int count) {
if (count < 1) return;
StringBuilder sb = new StringBuilder();
for (int i=0; i<count; i++) {
System.out.println(this.cryingSound);
sb.append(this.cryingSound);
}
System.out.println(sb.toString());
}
@Override
public void printName() {
System.out.println("Cat's Name : "+ this.name);
}
}
2. メソッドのオーバーロードとオーバーライド
'オーバーロード'と'オーバーライド'両方ともポリモーフィズムを意味に合いますが、内容自体が違います。
public void crying() {
System.out.println(this.cryingSound);
}
public void crying(int count) {
if (count < 1) return;
StringBuilder sb = new StringBuilder();
for (int i=0; i<count; i++) {
System.out.println(this.cryingSound);
sb.append(this.cryingSound);
}
System.out.println(sb.toString());
}
- オーバーロード : 同じ名前のメソッドを引数によって、違う機能するようにするのを言います。
- オーバーライド : 親のメソッドを子クラスで再定義すること、子クラスごとに違くメソッドを再定義し、違う結果を出せるのをいいます。
Dog dog = new Dog("Happy", 3, "Akita");
Person person = new Person("David", 20, "English");
Cat cat = new Cat("Mike", 10, "KoreanShotHair");
Map<String, Animal> map = new LinkedHashMap<String, Animal>();
map.put("dog", dog);
map.put("person", person);
map.put("cat", cat);
for (String key : map.keySet()) {
Animal animal = map.get(key);
animal.printName();
}
3. 親クラスの参照変数から呼び出せるのは?
子クラスのインスタンスを親クラスの参照変数から参照するとしても子クラスの全てのメソッドとメンバー変数を使えることではありません。親クラスの参照変数から呼び出せるのは親クラスで定義したメソッドとメンバー変数になります。
Animal animalInCat = map.get("cat");
animalInCat.printName();
animalInCat.getAge();
// animalInCat.crying(); // 子クラスのメソッドは使えない。
4. 子クラスの機能をまた使いたい場合は?
子クラスの機能をまた使いたい場合はインスタンスの型変換をすればよいです。
親から子クラスの参照型に型変換するのをダウンキャストと言い、子から親クラスの参照型に型変換するのをアップキャストと言います。
ダウンキャストの場合は必ずキャスト演算子を使い、明示的型変換をしなければなりません。
Cat catFromAnimal = (Cat)animalInCat;
catFromAnimal.crying();
5. instanceof演算子
親クラス複数の子クラスを持つ場合、親クラスの参照変数に何の子クラスのインスタンスが入っているのか確認しないといけない場合があるかもしれません。その様な場合はinstanceof演算子を用いて何のクラスのインスタンスか確認することができます。
map.put("animal", new Animal());
for (String key : map.keySet()) {
Animal animal = map.get(key);
if (animal instanceof Dog) {
System.out.println(key+"'s instanceof Dog");
} else if (animal instanceof Person) {
System.out.println(key+"'s instanceof Person");
} else if (animal instanceof Cat) {
System.out.println(key+"'s instanceof Cat");
} else if (animal instanceof Animal) {
System.out.println(key+"'s instanceof Animal");
}
}
※ 例示コード
https://github.com/leeyoungseung/algorithmBasic/blob/master/algorithm/src/objective/basic04
https://github.com/leeyoungseung/algorithmBasic/blob/master/algorithm/src/objective/basic05
※ 韓国語のポストは以下のURLで確認できます。
https://koiking.tistory.com/91