スライドショースライドショー

【納得Java】抽象クラス(abstract)を使うメリット

こんにちは!侍エンジニア インストラクターの本多です。

みなさんは、abstractクラス(抽象クラス)というものをご存知でしょうか?

ルールがいくつかあって使いにくいところもありますが、大規模開発では欠かせないものです。この記事では、Javaabstractクラスについて

  • abstractクラスとは何か
  • abstractクラスの使い方

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

  • abstractクラスの注意点
  • interfaceとの違い

といった応用的な内容に関しても解説していきます。今回はabstractクラスについて、わかりやすく解説していきます!

abstractクラスの利点とは

abstractクラスとは、抽象メソッドを1つ以上持つクラスです。まず抽象メソッドは何か?というところから解説します。

抽象メソッドとは実装を持たない、シグネチャ(メソッド名、引数の型、引数の数)と戻り値の型のみを定義するメソッドです。

具体的には、以下の通りです。先頭にabstractとついているところ、引数のカッコのあとに{ } がないところに注目してください。

abstract 戻り値の型名 メソッド名(引数);

次に、抽象クラスです。抽象クラスとは、抽象メソッドを1つ以上持つクラスです。

抽象クラスは下記のように記述します。

abstract class クラス名 {
    abstract 戻り値の型名 メソッド名(引数);
}

抽象クラスで抽象メソッドを持つ利点とは、開発者側にメソッドのオーバーライドを強制するということができることです。

抽象クラスを継承したサブクラスごとに抽象メソッドをオーバーライドして処理内容を記述する必要があります。

しかし、サブクラスごとに処理内容は別々にできます。サブクラスごとに処理内容はまちまちになる、でも必ず処理内容を記述しなければならない、という場合は抽象クラスで抽象メソッドを持つ利点を利用することになります。

抽象メソッドの使い方

抽象メソッドを使うには、抽象クラスを「extends」句で継承する必要があります。

下記のように記述します。

abstract class 抽象クラス名 {
    abstract 戻り値の型名 メソッド名(引数);
}

class 派生クラス名 extends 抽象クラス名 {
    戻り値の型名 メソッド名(引数) {
        処理内容;
    }
}

では、実際に抽象メソッドの使い方を見てみましょう。

abstract class AbstractClass {
    abstract void abstractMethod(int num, String str);
    
    void nonAbstractMethod() {
        System.out.println("非抽象メソッドより出力");
    }
}
 
public class Main extends AbstractClass {
 
    public static void main(String[] args) {
        Main main = new Main();
        main.abstractMethod(3, "Test");
    }
    
    public void abstractMethod(int num, String str) {
        System.out.println("引数int num = " + num + " / 引数String str = "+ str);
    }

}

実行結果:

引数int num = 3 / 引数String str = Test

AbstractClassを継承したMainクラスに実装を記述しています。

抽象クラスの注意点

抽象クラスを使う上で、いくつかルールがあります。

  • 直接インスタンス化できない。
  • 抽象メソッドは全てオーバーライドしなくてはならない。
  • サブクラスでコンストラクタを記述する必要がある

順に見ていきましょう。

直接インスタンス化できない

抽象クラスは、そのままでは使えません(つまり、インスタンス化できません)。

試しに、上記のAbstractClassをインスタンス化してみましょう。

abstract class AbstractClass {
    abstract void abstractMethod(int num, String str);
    
    void nonAbstractMethod() {
        System.out.println("非抽象メソッドより出力");
    }
}
 
public class Main extends AbstractClass {
 
    public static void main(String[] args) {
        // 直接インスタンス化してみる。
        AbstractClass ac = new AbstractClass();
        ac.abstractMethod(3, "Test");
    }
    
    public void abstractMethod(int num, String str) {
        System.out.println("引数int num = " + num + " / 引数String str = "+ str);
    }

}

実行結果:

Main.java:13: error: AbstractClass is abstract; cannot be instantiated

このサンプルコードでは、エラーメッセージが表示されます。

AbstractClassは抽象クラスなのでインスタンス化できません。

抽象メソッドのオーバーライド

抽象クラスの抽象メソッドは、必ず全てオーバーライドする必要があります。

先の例のメソッド名を変えて、抽象メソッドをオーバーライドしないように変更します。

abstract class AbstractClass {
    abstract void abstractMethod(int num, String str);
    
    void nonAbstractMethod() {
        System.out.println("非抽象メソッドより出力");
    }
}
 
public class Main extends AbstractClass {
 
    public static void main(String[] args) {
        Main main = new Main();
        main.abstractMethod(3, "Test");
    }
    
    // 抽象クラスに無いメソッド名に変更
    public void Method(int num, String str) {
        System.out.println("引数int num = " + num + " / 引数String str = "+ str);
    }

}

実行結果:

Main.java:9: error: Main is not abstract and does not override abstract method abstractMethod(int,String) in AbstractClass

abstractMethodをオーバーライドしていません、とエラーになりました。これが一体何の役に立つのでしょうか?

メリットは、開発者側にメソッドのオーバーライドを強制するということができます。クラスによってロジックはまちまちになる、でも必ず書かなくてはいけない、という場合はこの特性を利用できます。

コンストラクタを使う方法

abstractクラスのコンストラクタを使う方法について説明します。先ほどご説明したとおりabstractクラスは直接インスタンス化できません。

また、サブクラスではスーパークラスのコンストラクタを「super」句を使って継承する必要があります。

サブクラスはインスタンス化できるので、サブクラスをインスタンス化してスーパークラスから継承したコンストラクタを使用します。サンプルコードで確認しましょう。

// スーパークラス
abstract class AbstractClass {
    
    public AbstractClass(int num, String str) {
        System.out.println("引数int num = " + num + " / 引数String str = "+ str);
    }
    
    abstract void abstractMethod(int num, String str);
    
    void nonAbstractMethod() {
        System.out.println("非抽象メソッドより出力");
    }
}

// サブクラス
class SubClass extends AbstractClass {
    // サブクラスからスーパークラスのコンストラクタを呼び出し
    public SubClass(int num, String str) {
        super(num, str);
    }
    
    public void abstractMethod(int num, String str) {
        System.out.println("引数int num = " + num + " / 引数String str = "+ str);
    }
}
 
public class Main {
 
    public static void main(String[] args) {
        SubClass sc = new SubClass(3, "Test");
    }
    
}

実行結果:

引数int num = 3 / 引数String str = Test

このサンプルコードでは、SubClassクラスは抽象クラスAbstractClassを継承しています。SubClassクラス内で抽象クラスAbstractClassのコンストラクタを「super」句を使って継承しています。

Mainクラス内ではSubClassクラスをインスタンス化して抽象クラスAbstractClassのコンストラクタを使用しています。

なお、継承したクラスのコンストラクタについては、以下の記事にまとめていますので、ぜひ参考にしてくださいね!

【Java入門】継承とコンストラクタの呼び出し(super/this)
更新日 : 2018年11月20日

インターフェースとの違い

抽象クラスインターフェースとの違い、使い分けを表一覧にしてみました。

 抽象クラスインターフェース
抽象メソッドサブクラスで必ず実装抽象メソッドのみ記述
(自動でpublic abstract)
実装を持つメソッド実装可能実装不可(抽象メソッドのみ)
(Java8以降、defaultを使って実装可)
メンバ変数クラスのメンバ変数と同じ必ず定数(自動でpublic static final)
多重継承不可(単一継承のみ)可能

Java7以前は「インターフェースは直接インスタンス化できない」という違いがあったのですが、Java8以降はインターフェースも直接インスタンス化できてしまいます。

サンプルコードで確認しましょう

interface AbstractInterface {
    default void defaultMethod(){
        System.out.println("defaultMethodより出力");        
    }
    
    void abstractMethod();
}
 
public class Main {
 
    public static void main(String[] args) {
        AbstractInterface ac = new AbstractInterface() {
            public void abstractMethod(){
                System.out.println("オーバーライドしたabstractMethodより出力");
            }
        };
 
        ac.abstractMethod();
        ac.defaultMethod();
    }

}

実行結果:

オーバーライドしたabstractMethodより出力
defaultMethodより出力

では、抽象メソッドとインターフェースの違いは何かというと、多重継承ができるかどうかです。

インターフェースは下記のように複数のインターフェースを実装することができます。

class クラス名 implements インターフェース名1, インターフェース名2 {
    // 処理
}

よってインターフェースは、より柔軟な実装ができます。

ただし、多重継承を使いすぎると複雑になりすぎるというデメリットがあるので、十分注意する必要があります。

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

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

【Java入門】クラスの使い方総まとめ
更新日 : 2019年7月24日

interface(インターフェース)の使い方総まとめ

interface(インタフェース)のいろいろな使い方を次の記事にまとめているので、ぜひ確認してください!

【Java入門】interface(インタフェース)の使い方総まとめ
更新日 : 2019年4月26日

まとめ

この記事では、abstractクラスを説明しました

取り扱いのルールが難しいabstractですが、注意しながら使えば問題ありません。

使い方を忘れた場合、本記事を参考にしてくださいね!

LINEで送る
Pocket

無料でSEからWebエンジニアへ転職しませんか?



侍エンジニア塾では、完全未経験の方から現在SEだけどプログラミングはやっていないという経験者まで、幅広い方々の人生を好転させるプログラミング指導を行ってきました。SEの方とお話していくなかで、

  • システムエンジニアという職業だけどコードが書けない
  • 事務作業が多くスキルがないため将来が不安
  • スクールに通うと完全未経験者と同じスタートになるからレベルが合わない
という、すでに知識があるSEならではのお悩みがあることに気づきました。そんな方におすすめなのが、弊社の「転職コース 」です。

弊社では、マンツーマンでレッスンを行いますので、現在お持ちの知識レベルからカリキュラムを作成いたします。さらにこちらの転職コースは無料で受講を始められて転職成功でそのまま卒業できるというとてもお得なコースとなっています。

既に知識のあるSEといっても転職は年齢が若いほど受かりやすいため、まずは無料体験レッスンで今の現状や理想の働き方について一緒に考えていきましょう。

まずは無料体験レッスンを予約する

書いた人

本多 農

本多 農

関西在住のITエンジニアです。普通の会社に勤務しながら、侍エンジニアのインストラクター、ライターとして活動しています。

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説