クラスの継承
オーバーライド
スーパークラスのメソッドを上書きします。
@Override
目次
1. メソッドの上書き
重要
オーバーライド とは、
スーパークラスのメソッドを、サブクラスで再定義(上書き)することです。
スーパークラスのメソッドと
同じメソッドをサブクラスで定義すると、
そのまま上書きされるってだけだ。
なるほどね。
//Animal_01.java
public class Animal_01{
protected static String group = "生き物です。";
protected String name;
public Animal_01(){
this("no_name");
}
public Animal_01(String name){
this.name = name;
}
public static void printGroup(){
System.out.println(group);
}
public void printName(){
System.out.println(name + "だぞ! ガオー!");
}
}
//Dog_01.java
public class Dog_01 extends Animal_01{
public Dog_01(String name){
super(name);
}
//以下オーバーライドしたメソッド
@Override
public void printName(){
System.out.println(name + "だワン!");
}
}
//Cat_01.java
public class Cat_01 extends Animal_01{
public Cat_01(String name){
super(name);
}
//以下オーバーライドしたメソッド
@Override
public void printName(){
System.out.println(name + "なのにゃ!");
}
}
//Driver_24.java
public class Driver_24{
public static void main(String[] args){
Animal_01 animal01 = new Animal_01("アニマル浜口");
Dog_01 dog01 = new Dog_01("白いお父さん");
Cat_01 cat01 = new Cat_01("ニャース");
//それぞれのインスタンスで printNameメソッドを実行
animal01.printName();
dog01.printName();
cat01.printName();
}
}
4つのファイルすべてを wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_24.java
ws>java Driver_24
アニマル浜口だぞ! ガオー!
白いお父さんだワン!
ニャースなのにゃ!
語尾がクラスごとに変わった。
printNameメソッドが
上書きされたんだ。
2. @Override アノテーション
上にくっついている
「@Override」は
何の意味があるんすか?
実はこれ
なくても動くんだけど、
保険みたいなものかな?
@Override はアノテーションの一種です。
アノテーションは、「注釈」という意味で、プログラムの説明のようなものです。
@Override は、「スーパークラスのメソッドをオーバーライドします。」という意味です。
@Override には優れた機能があります。
スーパークラスに無いメソッドに @Override をつけると
コンパイルエラーで警告してくれます。
オーバーライドしたつもりが、メソッド名や引数が異なって、
オーバーライドできていない場合の気付きになります。
@Override アノテーション
スーパークラスに無いメソッドに @Override をつけると
コンパイルエラーで警告してくれます。
シートベルト並に
簡単便利なので
是非使ってみてほしい。
3. オーバーライドさせる条件
「スーパークラスのメソッドと同じメソッド」をサブクラスで定義するとオーバーライドされます。
「スーパークラスのメソッドと同じメソッド」 ってどこまで同じならオーバーライドされるのでしょうか。
上手く一致させないと
ただのメソッドの追加になっちゃう。
実は、シグネチャが同じ + α の条件でオーバーライドになります。
シグネチャが同じなだけじゃ
だめなの?!
スーパークラスのメソッドとサブクラスのメソッドが、
以下の条件を満たしていると
オーバーライドされます。
- シグネチャが同じ
- 戻り値のデータ型が同じ
- スーパークラスのメソッド以上のアクセス権限の付与
戻り値のデータ型が同じでないと
オーバーライドにならない。
重要
シグネチャが同じメソッドは、同一のメソッドと解釈されますが、
戻り値が異なるとオーバーライドできません。
(コンパイルエラーになります。)
以下のようなスーパークラスのメソッドは、無条件で オーバーライドできません。
オーバーライドできないメソッド
- private修飾子が付いているメソッド
- static修飾子が付いているメソッド
- final修飾子が付いているメソッド
4. オーバーライドできない例1 戻り値
ここ。
割とポイント。
以下の例では、
スーパークラス(Animal_01) の printNameメソッドの
戻り値が 「
void」、
サブクラス(Cat_31NG) の printNameメソッドの
戻り値が 「
int」です。
どちらの printNameメソッドも、シグネチャは
printName()です。
- シグネチャが同じなので、メソッドの追加と解釈されることはありません。
- @Overrideアノテーションがなくてもオーバーライドと解釈されます。
- 戻り値が異なるので、オーバーライド出来ず、コンパイルエラーになりました。
Animal_01.java の printNameメソッド抜粋
public class Animal_01{
public void printName(){
System.out.println(name + "だぞ! ガオー!");
}
}
//Cat_31NG.java
public class Cat_31NG extends Animal_01{
public Cat_31NG(String name){
super(name);
}
//@Override
public int printName(){
System.out.println(name + "なのにゃ!");
return 1;
}
public static void main(String[] args){
new Cat_31NG("ニャース");
}
}
Animal_01.java
Cat_31NG.java
を wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Cat_31NG.java
Cat_31NG.java:8: エラー:
Cat_31NGのprintName()はAnimal_01のprintName()をオーバーライドできません
public int printName(){
^
戻り値の型intはvoidと互換性がありません
エラー1個
そーゆーことか。
重要
継承関係にあるクラスを含めて
戻り値だけが異なるメソッドを許容しません。
5. オーバーライドできない例2 引数
以下の例では、
スーパークラス(Animal_01) の printNameメソッドの引数が なし、
シグネチャは printName()です。
サブクラス(Cat_31NG) の printNameメソッドの引数が 「double」です。
シグネチャは printName(double)です。
シグネチャが異なるので、オーバーロードと解釈されます。
@Overrideアノテーションを付けて、オーバーライドである旨を表明すると、
オーバーライドになってない旨のコンパイルエラーになりました。
Animal_01.java の printNameメソッド抜粋
public class Animal_01{
public void printName(){
System.out.println(name + "だぞ! ガオー!");
}
}
//Cat_32NG.java
public class Cat_32NG extends Animal_01{
public Cat_32NG(String name){
super(name);
}
@Override
public void printName(double b){
System.out.println(name + "なのにゃ!");
}
public static void main(String[] args){
new Cat_32NG("ニャース");
}
}
Animal_01.java
Cat_32NG.java
を wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Cat_32NG.java
Cat_32NG.java:6: エラー: メソッドはスーパータイプのメソッドを
オーバーライドまたは実装しません
@Override
^
エラー1個
6. オーバーライドできない例3 アクセス権限
以下の例では、
スーパークラス(Animal_01) の printNameメソッドのアクセス権限が 「public」、
サブクラス(Cat_33NG) の printNameメソッドのアクセス権限が 「protected」です。
どちらの printNameメソッドも、シグネチャは printName()です。
シグネチャが同じなので、オーバーライドと解釈されますが、
アクセス権限が弱くなっているので、コンパイルエラーになりました。
Animal_01.java の printNameメソッド抜粋
public class Animal_01{
public void printName(){
System.out.println(name + "だぞ! ガオー!");
}
}
//Cat_33NG.java
public class Cat_33NG extends Animal_01{
public Cat_33NG(String name){
super(name);
}
//@Override
protected void printName(){
System.out.println(name + "なのにゃ!");
}
public static void main(String[] args){
new Cat_33NG("ニャース");
}
}
Animal_01.java
Cat_33NG.java
を wsフォルダに保存して実行します。
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Cat_33NG.java
Cat_33NG.java:7: エラー: Cat_33NGのprintName()は
Animal_01のprintName()をオーバーライドできません
protected void printName(){
^
(public)より弱いアクセス権限を割り当てようとしました
エラー1個
こんなにきわどい
オーバーライド
しないだろうけどね。
お疲れ様でした。