多態性（ポリモーフィズム）

#基本的な考え方
継承の`is-a`の考え方を使って、インスタンスの大枠をプログラム上で認識させる。
例えば、`トラック`クラスから生成された、`トラック`インスタンスを、`自動車`クラスのインスタンスとしてプログラム上に認識させるための方法。

##インスタンスの大枠をプログラムで認識させる方法
自動車・トラックの例でいえば・・・

```java
Car car =new Truck
```
**①new Truck**
インスタンスを生成する。

**②Car car**
生成したインスタンスを何とみなすか。今回「トラッククラス」から生成したインスタンスだが、「自動車」としてみなすという意味になる。


##イメージ
①
<img width="941" alt="スクリーンショット 2018-03-04 11.14.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/229025/1187e9e4-3334-460a-90fe-42f6e371defe.png">


②
<img width="941" alt="スクリーンショット 2018-03-04 11.14.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/229025/b3d8dda6-0bf6-0225-fa59-0ae47bd30eab.png">

#親クラスに対して、子クラスから生成されたインスタンスを代入する

##考え方
親クラスに対して、子クラスから生成されたインスタンスを代入すると、子クラスのメンバは使用出来なくなる。

##イメージ
<img width="971" alt="多様性（親インスタンスへの代入）.png" src="https://qiita-image-store.s3.amazonaws.com/0/229025/eb29cfc8-1756-3523-9909-631ddf28e39e.png">

#親クラスと子クラスに同じ名前のメソッドがある場合の動き

##考え方
継承の考え方により、親クラスのメソッドを呼び出した際も、子クラスのメソッドが呼び出される。

##イメージ
<img width="1009" alt="スクリーンショット 2018-03-02 11.45.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/229025/97984e86-8155-7736-a353-e67d727962e6.png">



・上記図は`Wizard`としてみなす`Wizardインスタンス`と、`Character`としてみなす`Wizardインスタンス`の２種類がある。
・それぞれのメソッド`run`を呼び出しているが、`Character`としてみなす`Wizardインスタンス`にて、メソッド`run`を呼び出した場合、`Character`クラスのメソッドが呼び出されるかと思いきや・・・
・継承の考え方で**子クラス**のメソッドが優先的に呼び出されるため、`Wizard`クラスのインスタンスが呼び出される。

#インスタンスの大枠を、親クラス→子クラスに変更したい時
##考え方
上記例に置き換えると、`Character`としてみなす、`wizard`インスタンスを、`Wizard`としてみなす`wizard`インスタンスに変更したい時の方法。

##変更方法
**普通に考えると・・・**

```java
Wizard wizard2 = character;
```
で良さそうだけど、これだとエラーがでる・・・。
理由は、`Character`としてみなす、`wizard`インスタンスはこれまで`Character`という、大枠で捉えてきた。そのため、コンピュータからすると「これって本当に`wizard`なの？？`Character`って他にもいるよね？？」ってなる。

**そのため**

```java
Wizard wizard2 = (Wizard)character;
```
キャスト演算子を用いて、強制的にクラスを変更しなければならない。上記でいうと、(Wizard)型の変数に強制的に変更している。

**しかし**

```java
Character character = new Hero;//ヒーローはキャラクターとして捉える！
Wizard wizard2 = (Wizard)character;//ヒーローは魔法使いとして捉えろ！（？？）
```

上記のようなミスが発生する可能性もある。
・最初キャラクターとして捉える、ヒーローインスタンスを生成。
・魔法使いとして捉える、ヒーローインスタンスを生成。
これだと、**Is-aの関係が成り立たない**ため、`ClassCastException`(キャストによる強制変更が間違っている)というエラーになってしまう。
　・○ ヒーローはキャラクターです。
　・× ヒーローは魔法使いです。

つまり、キャストで強制変更出来るクラスのは、**インスタンスを生成した際に使用したクラスまたは、その子クラス以降のクラス**のみである。

##キャストによる強制変更が正しいか判断する方法
###方法
キャストによる強制変換が正しいか判別するために、javaでは`instanceof`演算子を使用する。
`instanceof`演算子は、キャスト演算子で指定された型に代入しても、矛盾しないかを判別する。

###例

```java
if(character instanceof Wizard){//もし、`character`を　`Wizard`としてみなして良いなら
 Wizard wizard2 = (Wizard)character;
}
```

#多様性のメリット

##処理をまとめる事が出来る

###考え方
インスタンス生成時に、クラス変数に配列を使用する事で、インスタンスに対してまとめた処理が出来る。

**配列を使わなかったら**
ヒーロークラスから`Hero1``Hero2``Hero3`、魔法使いクラスから`Wizard1``Wizard2``Wizard3`をそれぞれ生成して、全員に攻撃させたい場合

```java
//インスタンスの生成
Hero hero1 = new Hero();
Hero hero2 = new Hero();
Hero hero3 = new Hero();
Wizard wizard1 = new Wizard();
Wizard wizard2 = new Wizard();
Wizard wizard3 = new Wizard();

//メソッドの呼び出し
hero1.attack();
hero2.attack();
hero3.attack();
wizard1.attack();
wizard1.attack();
wizard1.attack();
```

これだとメソッドの呼び出しを同じ様な処理を繰り返してて、いまいちイケてない・・・。
 
**配列を使うと**

```java
//配列の作成
Character[] character = new Character[6];

//インスタンスの生成
Character character[0] = new Hero;
Character character[1] = new Hero;
Character character[2] = new Hero;
Character character[3] = new Wizard;
Character character[4] = new Wizard;
Character character[5] = new Wizard;

//メソッドの呼び出し
for(Character ch : character){
 ch.attack();
}
```
メソッドの処理がスッキリまとまって、いい感じ！

##引数をざっくり受け取る事が出来る
###例

**モンスターに攻撃したい場合**

```java
	public static void main(String[] args) {
		//配列変数の作成
		Monster[] monster = new Monster[4];
		//モンスターインスタンスの生成
		monster[0] = new Slime();
		monster[1] = new Slime();
		monster[2] = new Goblin();
		monster[3] = new Goblin();
		//ヒーローインスタンスの生成
		Hero hero = new Hero();
		//モンスターに攻撃
		hero.attack(monster[0]);
	}
```

```java

public class Hero {
	void attack(Monster monster) {
		monster.hp-=10;
	}
}
```
こうする事で、`Hero`クラスの`attackメソッド`の引数を、モンスターの種類毎に用意する必要が無くなる。

##異なる処理結果の処理をまとめる事が出来る
###考え方
親クラスのクラス名でメソッドを呼び出しても、子クラスのメソッドが呼び出されるため、メソッドの呼び出しをまとめる事が出来る

###例
スライムクラス

```java
public class Slime extends Monster {
	public void run() {
		System.out.println("スライムはうねうね逃げ出した！");
	}
}
```
ゴブリンクラス

```java
public class Goblin extends Monster{
	public void run() {
		System.out.println("ゴブリンはドタバタ逃げ出した！");
	}
}
```

モンスタークラス

```java

public abstract class Monster {
	String name;
	int hp = 50;
	public abstract void run();
}
```

メインメソッド

```java
//モンスターインスタンスの生成
monster[0] = new Slime();
monster[1] = new Goblin();
//モンスタークラスでメソッドを呼び出し
for(Monster mo:monster) {
mo.run();
```
出力結果

```java

スライムはうねうね逃げ出した！
ゴブリンはドタバタ逃げ出した！
```

モンスタークラスで呼び出しているが、それぞれ中身のクラスのメソッド内容が実行される。
この際、必ず親メソッドにも呼び出すメソッドを`abstrack`で定義する必要がある。