【Java】A a = new B()を考える第1弾

## A a = new B()とは何をしているのか
前提としてAクラスはBクラスのスーパークラスである。つまり、AクラスとBクラスは継承の関係にある。

## A a = new B()を見てみる(インスタンスメソッド版)
```ruby:Java(A.java)
public class A{
	public void speak() {
		System.out.println("Hello");
	}
}
```

```ruby:Java(B.java)
public class B extends A{
	public void speak() {
		System.out.println("Good Morning");
	}
}
```

ここでBはAを継承し、speakメソッドをオーバーライドしている。この時Mainクラスで以下のような処理を行う。
```ruby:Java(Main.java)
public class Main {
	static int num;
	public static void main(String[] args) {
		A a = new B();
		a.speak();
	}	
}
```

:::note info
**オーバーライドする時のアクセス修飾子**
サブクラスではアクセスレベルが同じ、または緩い修飾子で宣言する。また、privateで修飾されたメソッドはオーバーライドできない。
:::

結果は…
```
Good Morning
```

Bクラスのspeakメソッドが呼び出された。オブジェクトa自体はスーパークラスの型(A)だが、インスタンスメソッドをオーバーライドしている場合はサブクラスのメソッドが優先して呼び出される。

## サブクラスにインスタンスメソッドが無かったら(インスタンスメソッド版)
次はサブクラスのspeakが存在しない状態で動かしてみる。speakメソッドをohayoメソッドに置き変えて実行。

```ruby:Java(B.java)
public class B extends A{
	public void ohayo() {
		System.out.println("Good Morning");
	}
}
```

結果
```
public class Main {
	static int num;
	public static void main(String[] args) {
		A a = new B();
		a.speak();
	}	
}
```

今度はスーパークラスのメソッドが呼び出された。優先度はサブクラスの方が高いが、メソッドが存在しない場合はスーパークラスのメソッドが呼び出される。

## スーパークラスにインスタンスメソッドが無かったら(インスタンスメソッド版)
今度はスーパークラスのspeakを消して実行してみる。B.javaはspeakがある状態に戻して、A.javaのspeakメソッドをohayoメソッドに置き変える。

```ruby:Java(A.java)
public class A{
	public void ohayo() {
		System.out.println("Hello");
	}
}
```

結果
```
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	メソッド speak() は型 A で未定義です

	at Main.main(Main.java:4)
```

今度はエラーになった。変数aはBのインスタンスを参照しているが、a自体はA型なのでクラスAに存在しないインスタンスメソッドは呼び出せない。

## A a = new B()をやってみる(staticメソッド版)
同じことをstaticメソッド(クラスメソッド)で実施してみる。
```ruby:Java(A.java)
public class A{
	public static void speak() {
		System.out.println("Hello");
	}
}
```
```ruby:Java(B.java)
public class B extends A{
	public static void speak() {
		System.out.println("Good Morning");
	}
}
```

```ruby:Java(Main.java)
public class Main {
	public static void main(String[] args) {
		A a = new B();
		a.speak();
	}	
}
```

結果
```
Hello
```

今度はスーパークラスのspeakが呼び出された。これは**ポリモフィズム**という考え方が関係している。

:::note info
**ポリモフィズムとは**
オブジェクト指向の1つで、共通のインタフェースでを持つ操作でも、実際にオブジェクトごとにふるまいや動作が異なることをいう。特に継承や実装はメソッドを合わせるだけでなく、スーパークラスやインタフェースの型で実際のオブジェクトを扱え、操作の呼び出しができる。
:::

インスタンスメソッドではポリモフィズムが適用されるが、staticメソッドでは適用されない。そのため上記のような結果になる。

## サブクラスにstaticメソッドが無かったら(staticメソッド版)
次はサブクラスのspeakが存在しない状態で動かしてみる。speakメソッドだった部分をohayoメソッドに置き変えて実行。

```ruby:Java(B.java)
public class B extends A{
	public static void ohayo() {
		System.out.println("Good Morning");
	}
}
```

結果
```
Hello
```

変わらずスーパークラスのメソッドが呼び出された。staticメソッドではポリモフィズムが適用されないので、サブクラスがどうなっていようが関係ない。

## スーパークラスにstaticメソッドが無かったら(staticメソッド版)
今度はスーパークラスのspeakを変更し手実行してみる。B.javaはspeakがある状態に戻して、A.javaのspeakメソッドをohayoメソッドに置き変える。

```ruby:Java(A.java)
public class A{
	public static void ohayo() {
		System.out.println("Hello");
	}
}
```

結果
```
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	メソッド speak() は型 A で未定義です

	at Main.main(Main.java:4)
```

インスタンスメソッドと同様のエラーになった。ポリモフィズムは適用されないため、純粋にA型のメソッドを見に行った結果、該当するメソッドが無い状態になった。

## まとめ
* A a = new B()を実施。インスタンスメソッドがオーバーライドされた場合、Bのメソッドが呼び出される
* サブクラスに該当インスタンスメソッドが無い場合、スーパークラスのメソッドが呼び出される
* スーパークラスに該当インスタンスメソッドが無い場合、コンパイルエラー
* A a = new B()を実施。staticメソッドの場合はポリモフィズムが適用されないので、Aのメソッドが呼び出される
* サブクラスに該当staticメソッドが無い場合も、Aのメソッドが呼び出される
* スーパークラスに該当staticメソッドが無い場合、コンパイルエラー