オーバーライド - @Override - 萌えJava超入門
クラスの継承

オーバーライド

スーパークラスのメソッドを上書きします。

@Override

目次

1. メソッドの上書き


重要
オーバーライド とは、
 スーパークラスのメソッドを、サブクラスで再定義(上書き)することです。

萌えJava超入門
スーパークラスのメソッドと
同じメソッドをサブクラスで定義すると、
そのまま上書きされるってだけだ。
「同じメソッド」の定義は、以下で触れます。

萌えJava超入門 萌えJava超入門
なるほどね。
Animal_01.java(再出)
  //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(再出)
//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
アニマル浜口だぞ! ガオー!
白いお父さんだワン!
ニャースなのにゃ!


萌えJava超入門 萌えJava超入門
萌えJava超入門
語尾がクラスごとに変わった。
printNameメソッドが
上書きされたんだ。


2. @Override アノテーション


萌えJava超入門 萌えJava超入門
上にくっついている
@Override」は
何の意味があるんすか?



萌えJava超入門
実はこれ
なくても動くんだけど、
保険みたいなものかな?
@Override はアノテーションの一種です。
アノテーションは、「注釈」という意味で、プログラムの説明のようなものです。
@Override は、「スーパークラスのメソッドをオーバーライドします。」という意味です。

@Override には優れた機能があります。
スーパークラスに無いメソッドに @Override をつけると
コンパイルエラーで警告してくれます。

オーバーライドしたつもりが、メソッド名や引数が異なって、
オーバーライドできていない場合の気付きになります。

@Override アノテーション
 スーパークラスに無いメソッドに @Override をつけると
 コンパイルエラーで警告してくれます。

萌えJava超入門 萌えJava超入門 萌えJava超入門
シートベルト並に
簡単便利なので
是非使ってみてほしい。


3. オーバーライドさせる条件


スーパークラスのメソッドと同じメソッド」をサブクラスで定義するとオーバーライドされます。
「スーパークラスのメソッドと同じメソッド」 ってどこまで同じならオーバーライドされるのでしょうか。

萌えJava超入門
上手く一致させないと
ただのメソッドの追加になっちゃう。
実は、シグネチャが同じ + α の条件でオーバーライドになります。

萌えJava超入門 萌えJava超入門
シグネチャが同じなだけじゃ
だめなの?!
スーパークラスのメソッドとサブクラスのメソッドが、
以下の条件を満たしているとオーバーライドされます。
  • シグネチャが同じ
  • 戻り値のデータ型が同じ
  • スーパークラスのメソッド以上のアクセス権限の付与

萌えJava超入門
戻り値のデータ型が同じでないと
オーバーライドにならない。
重要
 シグネチャが同じメソッドは、同一のメソッドと解釈されますが、
 戻り値が異なるとオーバーライドできません。
         (コンパイルエラーになります。)

以下のようなスーパークラスのメソッドは、無条件で オーバーライドできません。
オーバーライドできないメソッド
  • private修飾子が付いているメソッド
  • static修飾子が付いているメソッド
  • final修飾子が付いているメソッド



4. オーバーライドできない例1 戻り値


萌えJava超入門 萌えJava超入門 萌えJava超入門
ここ。
割とポイント。
以下の例では、
スーパークラス(Animal_01) の printNameメソッドの戻り値が 「void」、
サブクラス(Cat_31NG) の printNameメソッドの戻り値が 「int」です。
どちらの printNameメソッドも、シグネチャは printName()です。
  1.  シグネチャが同じなので、メソッドの追加と解釈されることはありません。
  2.  @Overrideアノテーションがなくてもオーバーライドと解釈されます。
  3.  戻り値が異なるので、オーバーライド出来ず、コンパイルエラーになりました。

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個

萌えJava超入門 萌えJava超入門
そーゆーことか。
萌えJava超入門
重要
 継承関係にあるクラスを含めて
 戻り値だけが異なるメソッドを許容しません。



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個

萌えJava超入門 萌えJava超入門 萌えJava超入門
こんなにきわどい
オーバーライド
しないだろうけどね。



お疲れ様でした。




© 2019 awasekagami