メモ置き場

メモ置き場です.開発したものや調べたことについて書きます.

[tex: ]

Javaの勉強(2):継承

Javaの継承についてまとめておく.

継承とは

Javaはメソッドや変数といったメンバを持ったクラスを定義し,クラス単位でプログラムを組み立てていく.機能ごとにクラスを作りプログラム中で利用していくわけだが,同じような機能を持ったクラスを複数定義しなければいけない場合などはプログラムが冗長になってしまう.ある機能を持ったクラスを作成しその機能に加えて新しいクラスを作成する,とすればプログラムの再利用性も高まるし,コードの見通しもよくなる.このようにあるクラスの機能を引き継いぎつつ新しいクラスを作ることを継承という.

スーパークラスとサブクラス

継承されるクラスを親クラスとかスーパークラスという.継承して新しく定義したクラスをサブクラスとか子クラスという.

多重継承

親クラスが複数あるようなクラスを作ることを多重継承という.Javaでは多重継承することはできない.つまりあるクラスのスーパークラスはただ一つしか存在しない.

スーパークラスが一つしかないというのは,直接継承しているクラスが一つしかないということを意味する.スーパークラススーパークラススーパークラスの…のように,何世代も前のスーパークラスというものは存在できる.

逆に,あるクラスから継承されてできたクラスは複数存在していても良い.つまりクラスは複数のサブクラスを持つことができる.

Objectクラス

Javaのクラスはただ一つのスーパークラスしか持つことができない.継承せずにクラスを作った場合はスーパークラスを持たないのだろうか?実は,継承をしないようにクラスを作成した場合,自動的にObjectというクラスがスーパークラスになる.

ObjectクラスとはJavaが提供するクラスで,Javaのクラスの根っこに位置するクラスである.どんなクラスも,スーパークラスをたどっていくとObjectクラスに到達する.
Objectクラスの説明はこちらを参考に.https://docs.oracle.com/javase/jp/8/docs/api/

継承のやり方

実際にコーディングするときは,クラス定義時にextendsで継承するクラスを指定する.

// super class
// MySuper.java
public class MySuper{
    private int number1;  // sub classからsuper.number1の形でアクセスできない
    protected int number2; // sub class からsuper.number2の形でアクセス可能.

    public MySuper(int number1, int number2){
        this.number1 = number1;
        this.number2 = number2;
        System.out.println("MySuper constructor");
    }

    public void sayHello(){
        System.out.println("Hello from MySuper class");
        System.out.println(number1 + "    " + number2);
    }

    public int getNumber1(){
        return number1;
    }

    public int getNumber2(){
        return number2;
    }

    public void printInfo(){
        System.out.println("Super Class!");
    }
}
// sub class
// MySub.java
public class MySub extends MySuper{ // extendsで継承するクラスの指定
    private int number3;

    public MySub(int number1, int number2, int number3){
        super(number1, number2);
        this.number3 = number3;
    }

    public MySub(){
        this(0,0,0);
    }

    public void sayHelloSub(){
        System.out.println("Hello from MySub");
        System.out.println(super.getNumber1() + "   " + super.getNumber2() + "   " + number3);
    }

    @Override
    public void printInfo(){
        System.out.println("Sub Class!");
    }
}
// Main.java
public class Main{
    public static void main(String[] args){
        MySub mySub = new MySub(1,2,3);
        mySub.sayHelloSub();
    }
}
実行結果
MySuper constructor
Hello from MySub
1   2   3

superとthis

superとthisという変数が出てきた.superとは,このクラスのインスタンススーパークラス部分を指すものである.以下のような使い方がある.

  • super()

スーパークラスのコンストラクタを呼ぶ.superで引数を与えるとシグネチャによってよばれるコンストラクタが変わる.スーパークラスのメンバ変数を初期化する場合などに使う.上の例だと,MySubクラスのコンストラクタでsuper(number1, number2);の形で使われている.

  • super.method()

スーパークラスのメソッドを呼び出すときに使う.オーバーライドしたメソッドに対して,super.method()と呼び出すとスーパークラスで定義されたメソッドが呼び出される.上の例だと,MySubクラスのsayHelloSubメソッドでsuper.getNumber1()などが使われている.

  • super.variable

変数を呼び出すもの.カプセル化に反するやり方なのであんまり使わない.基本的にsetterやgetterなどを呼び出す.

thisは,「このインスタンス」を表す.以下のような使い方がある.

  • thisで単独使用

インスタンスを戻り値として返したり,呼び出すメソッドの引数として渡したりできる.この方法で使ったことがまだないのでよくわからない.

  • this()

オーバーロードしている他のコンストラクタを呼び出すことができる.各コンストラクタの最初の行にしか書くことができない.上の例だと,MySubクラスの引数なしコンストラクタの定義でthis(0,0,0);の形で使われている.

  • this.variable

このインスタンスのメンバであることを表す.引数として渡されたローカル変数とメンバ変数を区別するときに使う.

オーバーライド

オーバーライドとは,スーパークラスで定義されたメソッドをサブクラスで定義し直すことである.サブクラスからメソッドを呼ぶと,オーバーライドされた処理が実行される.オーバーライドをする場合は@Overrideとつける

@Overrideについて

@で始まるJavaの文章をアノテーションという.プログラムの内容には関係ないが,コンパイラに情報を伝えるものとして使う.オーバーライドしていることをコンパイラに伝えるためにつける必要がある.例えば,typoなどでオーバーライドしたいメソッドとは異なる名前をつけてしまったりしたとする.そうすると本来オーバーライドしたかったのにサブクラスで新しく定義されるメソッドとしてコンパイラに解釈されてしまう.これを防ぐために@Overrideをつけておく.オーバーライドする関数がないとコンパイルエラーになるので,ミスが防げるようになる.

final演算子

  • finalクラス

継承できないクラスになる.public final class HogeHoge{... と使う.

  • finalメソッド

オーバーライドできないメソッドになる.

  • final変数

変更できない変数,つまり定数になる.コンストラクタで初期化しないとダメなはず.