0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Java Silver確実合格を目指すカレンダーAdvent Calendar 2024

Day 13

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

Last updated at Posted at 2024-12-12

前回

B b = (B)aの挙動を見てみよう(インスタンスメソッド版)

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

復習だが、BはAを継承し、speakメソッドをオーバーライドしている。この時、Mainクラスで以下の処理を実施する。

Java(Main.java)
public class Main {
	public static void main(String[] args) {
		A a = new B();//復習
		a.speak();//復習
		B b = (B)a;
		b.speak();
	}	
}

問題はA型の変数aをキャスト演算子で明示的にB型とし、B型の変数bに格納していることである。

キャスト演算子をつけない場合
以下のコンパイルエラーが発生するので、ダウンキャストの場合は必ずつける

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	型の不一致: A から B には変換できません

	at Main.main(Main.java:5)

さて結果はどうなるだろうか。

Good Morning
Good Morning

変数bはB型なので、Bクラスのspeakが呼び出された。

B b = (B)aの挙動を見てみよう(staticメソッド版)

ではspeakメソッドにstaticをつけて確認しよう。

Java(A.java)
public class A{
	public static void speak() {
		System.out.println("Hello");
	}
}

Java(B.java)
public class B extends A{
	public static void speak() {
		System.out.println("Good Morning");
	}
}
Java(Main.java)
public class Main {
	public static void main(String[] args) {
		A a = new B();//復習
		a.speak();//復習
		B b = (B)a;
		b.speak();
	}	
}

結果

Hello
Good Morning

この場合もBクラスのspeakが呼び出されることに注意。インスタンスメソッドと同様に元の型であるB型にキャストで戻し、B型で宣言した変数に代入しているため、呼び出すメソッドもBクラスのものになる。

Bクラスだけに存在するメソッドを呼び出す時は?(staticメソッド版)

今度は以下のようにBクラスにのみbyeメソッドを追加する。

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

それをMainクラスで呼び出そう。

Java(Main.java)
public class Main {
	public static void main(String[] args) {
		A a = new B();
		a.bye();
		B b = (B)a;
		b.bye();
	}	
}

結果

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

	at Main.main(Main.java:4)

上記のようにエラーになることは想像しやすいだろう。一旦エラー部分をコメントアウトして再確認する。

Java(Main.java)
public class Main {
	public static void main(String[] args) {
		A a = new B();
//		a.bye();
		B b = (B)a;
		b.bye();
	}	
}

結果

bye

b.bye()の結果はエラーにならなかった。このことからもbはB型で定義できていることがよくわかる。

まとめ

  • インスタンスメソッドの場合、実際のオブジェクト(new B())に基づいて、サブクラスのメソッドが優先的に呼び出される
  • staticメソッドの場合、変数の型(A)に基づいてメソッドが決定される
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?