今からでも遅くない!クラスの継承(extends)を学ぼう!【Java】

作ったクラスをコピーして、コピーしたクラスに機能を追加したいと思ったことありませんか?

例えば、RPGでゲームを作る時に「人間」クラスを作り、「剣士」「魔法使い」「アーチャー」と個別でキャラクターの機能を追加したい場合どうすればよいでしょうか?

クラスの継承という機能を使うことでこれらを実現することができます。

継承は継承元となるクラスのメンバ変数やメンバメソッドをあらためて記述する必要がなく使うことができて便利です。

この記事では、クラスの継承について

・クラスの継承とは
・基底クラスを継承するメリットとは

という基本的な内容から、

・インターフェースの実装とクラスの継承の違い
・メソッドをオーバーライドするメリットとは
・継承したクラスでのコンストラクタの扱い方

など具体的な使い方についても解説していきます。

今回はクラスの継承について、使い方をわかりやすく解説します!

なお、Javaの記事については、こちらにまとめています。

目次

クラスの継承とは

あるオブジェクトの属性(メンバ変数)やその属性を使った処理(メンバメソッド)で共通するメンバ(メンバ変数とメンバメソッド)を集めたクラスがあるとします。

このクラスに対して、共通するメンバはそのまま使用しつつも新たな属性や処理(メンバ)を加えることをクラスの継承といいます。

共通するメンバを集めた継承元のクラスのことを「基底クラス」、「スーパークラス」、「親クラス」などと呼びます。

また基底クラスを継承したクラスのことを「派生クラス」、「サブクラス」、「子クラス」などと呼びます。

派生クラスでは、基底クラスの処理を変えたい場合にその処理のメソッド名や引数を変えることなく、別の処理を記述することもできます。

これをメソッドのオーバーライドと呼びます。

基底クラスをextendsで継承するメリットとは

基底クラスを継承する方法について説明します。

継承を使うには「extends」句を用います。

派生クラスのクラス名の後ろに「extends」句を記述しその後に基底クラス名を記述します。

派生クラスは下記のような記述になります。

<publicなどの修飾詞> 派生クラス名 extends 基底クラス名 { }

ちなみに基底クラスの記述方法は通常のクラスの記述方法と変わりません。

また、派生クラスでは基底クラスのメンバ変数やメンバメソッドをそのまま使うことができます。

あらためて派生クラス内で使いたいメンバ変数やメンバメソッドを記述する必要はありません

それではサンプルコードで使い方をみていきましょう。

// 基底クラス
class ClassSuper{
    // メンバ変数
    protected int i1;
    protected int i2;
 
    // メンバメソッド
    public void calc1(int i1, int i2){
        this.i1 = i1;
        this.i2 = i2;
        System.out.println("i1 + i2 = " + (this.i1 + this.i2)); // 加算
    }
}
 
// 派生クラス(基底クラスを継承したクラス)
class ClassSub extends ClassSuper{
    // 追加のメンバ変数
    private int i3;
    private int i4;
    
    // 追加のメンバメソッド
    public void calc2(int i3, int i4){
        this.i3 = i3;
        this.i4 = i4;
        System.out.println("i1 * i2 = " + (this.i1 * this.i2)); // 乗算
        System.out.println("i3 - i4 = " + (this.i3 - this.i4)); // 減算
        System.out.println("i3 / i4 = " + (this.i3 / (double)this.i4));// 除算
    }
}
 
public class Main {
 
    public static void main(String[] args) {
        // 基底クラスのインスタンス生成
        ClassSuper cs1 = new ClassSuper();
        // 基底クラスのメンバ変数とメンバメソッドを使用
        cs1.calc1(1, 2);
 
        // 派生クラスのインスタンス生成
        ClassSub cs2 = new ClassSub();
        // 基底クラスのメンバ変数とメンバメソッドを使用
        cs2.calc1(1, 2);
        // 派生クラスで追加したメンバ変数とメンバメソッドを使用
        cs2.calc2(3, 4);
 
    }
 
}

実行結果:

i1 + i2 = 3
i1 + i2 = 3
i1 * i2 = 2
i3 - i4 = -1
i3 / i4 = 0.75

このサンプルコードでは、基底クラスであるClassSuperクラス内にint型のi1変数、i2変数とcalc1メソッドがあります。

これを派生クラスであるClassSubクラスで継承しています。

派生クラスであるClassSubクラスにはint型のi1変数、i2変数とcalc1メソッドの記述はありませんが、基底クラスであるClassSuperクラスのcalc1メソッドを呼び出し、int型のi1変数、i2変数への値の代入と計算結果の表示が実行されています。

変数名が同じ場合には、変数名に「this.」句をつけて引数で代入される変数名と区別します。

継承することで、派生クラスであらためて基底クラスのメンバを記述することなく、基底クラスと同じ処理を実行することができています。

このように、派生クラスでは基底クラスのメンバ変数とメソッドを再定義する必要なく使用することができます。

インターフェースの実装とクラスの継承の違い(implements)

クラスに似た機能として、インターフェースというものがあります。

インターフェースは抽象クラスのように継承して使いますが、インターフェースの場合は「継承」ではなく、「実装」と呼びます。

クラスでは複数のクラスを継承する多重継承はできませんが、インターフェースは多重継承のように複数のインターフェースを実装をすることができます。

インターフェースについてはこちらの記事で詳しく解説しているので、ぜひ確認してください。

メソッドをオーバーライドするメリットとは

メソッドのオーバーライドとは、派生クラスで基底クラスの処理をメソッド名や引数を変えることなく、別の処理に書き換えることです。

書き換えた後に「super」句を用いて、書き換える前の処理内容を実行することも可能です。

詳しくは別の記事で解説していますので、下記のリンク先を参照してくださいね!

継承したクラスでのコンストラクタの扱い方

継承したクラスでは基底クラスのコンストラクタを記述する必要があります。

とはいっても、派生クラスでも同じ内容を記述する必要はありません

super」句を使って手短に記述することができます。

詳しくは別の記事で解説していますので、下記のリンク先を参照してくださいね!

クラスについてもっと詳しく知りたい方へ

クラスのさまざまな使い方については、以下の記事にまとめていますので、ぜひ参考にしてくださいね!

まとめ

ここでは、基底クラスを継承するメリットやメソッドをオーバーライドするメリット、継承したクラスでのコンストラクタの扱い方について説明しました。

クラスの継承を使うことで、派生クラスでは基底クラスのメンバ変数やメンバメソッドをあらためて記述する必要がなくなります

そうすることで、コードも読みやすくなり後々の修正やメンテナンスがしやすくなり便利です。

この便利な仕組みを使いこなすことができるように、この記事を何度も参考にして下さいね!

この記事を書いた人

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
info@sss-lab.com

目次