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?

オーバーライドを整理する

Posted at

はじめに

javaのオーバーライドを深堀していたらややこしくなってしまったので、整理しておきます。

コード例

class A{
	List<Number> method(Number i){
		return new ArrayList<Number>();
	}
}

class B extends A{
	
	//例①
	List<Number> method(Number i){
		return new ArrayList<Number>();
	}
	
	//例②
	ArrayList<Number> method(Number i){
		return new ArrayList<Number>();
	}
	
	//例③
	List<Integer> method(Number i){
		return new ArrayList<Number>();
	}
	
	//例④
	List<Number> method(Integer i){
		return new ArrayList<Number>();
	}
	
}

Bクラス内に、親クラスAのmethodメソッドを実装した4例があります。

例①:戻り値・戻り値のジェネリクス・引数の型すべて一致
例②:戻り値が継承元戻り値のサブクラス
例③:戻り値のジェネリクスが継承元ジェネリクスのサブクラス
例④:引数の型が継承元引数のサブクラス

この中で、コンパイルが通る例はどれでしょう?
(すべて実装するのではなく、一つを選んで実装した場合と解釈してください)

正解は、例①、例②、例④ です。

解説

オーバーライドの条件は以下です。

メソッド名:
スーパークラスのメソッド名と完全に一致
引数:
スーパークラスのメソッドのシグネチャ(引数の型、数、並び)が完全に一致
戻り値の型:
スーパークラスのメソッドの戻り値の型と一致、または、スーパークラスの戻り値の型のサブクラス

これをもとに、例を見ていきましょう。

例①:戻り値・戻り値のジェネリクス・引数の型すべて一致
コンパイル可能
メソッド名・シグネチャ・戻り値型が完全に一致しているため、問題なくオーバーライドできます。

例②:戻り値が継承元戻り値のサブクラス
コンパイル可能
ArrayListはListのサブクラスのため、こちらも問題なくオーバーライドできます。

例③:戻り値のジェネリクスが継承元ジェネリクスのサブクラス
コンパイル不可
ここがややこしいところです...
ジェネリクス型は不変であるため、サブクラスであっても互換性はありません
そのため、ArrayList<A>とArrayList<B>に関係はなく、コンパイルエラーとなってしまいます。

例④:引数の型が継承元引数のサブクラス
コンパイル可能。ただし、オーバーライドではない。
さらにややこしいところです.....
先述した通り、オーバーライドはシグネチャの完全一致が条件です。
そのため、型がサブクラスであったとしても関係なくオーバーライドにはなりません。
ただし、今回の場合オーバーロードが成立するため、コンパイルは問題なく通ることになります。

おわりに

学べば学ぶほどややこしくなりますね、、
ここは基礎的な部分なので、しっかりと抑えたいと思います。

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?