抽象クラス - abstract - 萌えJava超入門
クラスの継承

抽象クラス

中身が無いメソッドを持つ不完全なクラス

abstract

目次

1. 抽象クラス


抽象クラス
  抽象クラスとは、「抽象メソッド」を持つクラスのことです。

抽象クラスには、必ず abstract 修飾子 を付与します。
(アブストラクトって読みます。)

抽象クラスと abstract 修飾子
  public abstract class AbstClass01{
        //中身
  }

萌えJava超入門
抽象メソッドって
なに?


2. 抽象メソッド


抽象メソッド
  抽象メソッドはと、処理内容を記述していないメソッドのことです。

抽象メソッドにも、必ず abstract 修飾子 を付与します。
メソッドの中身の部分「{}」(波カッコ)は書かずに、
そのまま「;」(セミコロン)で閉めます。
引数や戻り値の記述は必要です。
尚、「()」(丸かっこ)があることで、メソッドであることを示しています。

抽象メソッドの書き方
  public abstract void abstMethod01();
注: クラスメソッド(staticメソッド)を 抽象メソッドにすることはできません。
萌えJava超入門
え?
こんなのあり?


3. 実装とは


萌えJava超入門 萌えJava超入門 萌えJava超入門
とりあえず
言葉だけ覚えよう。
実装とは
  1. メソッドの中身の部分「{}」(波カッコ)の中を「メソッドの実装」といいます。
  2. 実装する」のように、動詞的な使い方をすることもあります。
    その場合、「{}」の中を記述する意味で使います。
      言葉の使用例:
       抽象メソッドとは、実装されていないメソッドのことです。
       抽象クラスは、サブクラスで抽象メソッドを実装してから使います。
  3. インターフェースを implements することも、「実装する」といいます。(後述)

萌えJava超入門
この辺は
そんなに厳密じゃない。
言葉の使い分け
 「オーバーライドする」は、
   すでに実装されているメソッドの書き換えのニュアンスが強いです。
 「実装する」は、
   抽象メソッド(実装が空)に処理を記述する時に使います。

  書き換える事を「実装する」とはあまり言わないのに対して、
 「オーバーライドする」は、抽象メソッドに処理を記述する場合でも使います。

実装する
  「実装する」は、{} の中を記述すること。



3. 抽象クラスは不完全なクラス

抽象クラスは、一部のメソッドの処理内容が書かれていない、不完全なクラスです。
このため、抽象クラスはインスタンスを生成することができません。
抽象クラスを継承して、サブクラスを使いましょう。

すべての抽象メソッドを実装すると、普通のクラスとして使用できます。
すべてのメソッドが実装されたクラスは「具象クラス」と呼ぶことがあります。

実装していないメソッドがあるサブクラスも、抽象クラスになります。

萌えJava超入門 萌えJava超入門
やっぱり
そのままでは
使えないんですね。


5. 抽象クラスのテンプレ

抽象クラスのテンプレ
  public abstract class AbstClass01{

        public abstract void abstMethod01(); //抽象メソッド1
        public abstract void abstMethod02(); //抽象メソッド2
        //普通のメソッドも共存可
        public final void method01(){
            System.out.println("method01");
        }
  }

↓↓↓ AbstClass01クラスの継承 ↓↓↓

抽象クラスの継承テンプレ
  public subClass extends AbstClass01{

        //抽象メソッドの1実装(必須)
        @Override
        public void abstMethod01(){
            System.out.println("abstMethod01");
        }
        //抽象メソッド2の実装(必須)
        @Override
        public void abstMethod02(){
            System.out.println("abstMethod02");
        }

        //method01 も普通に継承されます。
  }

萌えJava超入門 萌えJava超入門
extendsで継承するのは
普通のクラスと同じっスね。
萌えJava超入門
「subClass」は普通のクラスとして
利用することができるぞ。


6. 抽象クラスの継承サンプル

以下のAnimalEmbryoクラスは、
printNameメソッドを抽象メソッドに持つ抽象クラスです。
//AnimalEmbryo.java

//抽象クラス
public abstract class AnimalEmbryo{

    protected String name;
    public AnimalEmbryo(String name){
        this.name = name;
    }
    public abstract void printName(); //抽象メソッド

}

萌えJava超入門
前述の Animal_01クラスでは
printNameメソッドで「ガオー」
と表示されたが、
AnimalEmbryoクラスでは
抽象メソッドだ。
萌えJava超入門 萌えJava超入門
AnimalEmbryoクラスは
抽象クラスなんスね。

抽象クラスは、サブクラスで抽象メソッドを実装しなければ、クラスとして使用できません。
実際に AnimalEmbryoクラスを継承してみましょう。

//Dog_81.java

public class Dog_81 extends AnimalEmbryo{
    public Dog_81(String name){
        super(name);
    }
    @Override
    public void printName(){
        System.out.println(name + "だぞ! ワンワン!");
    }
}

//Cat_81.java

public class Cat_81 extends AnimalEmbryo{
    public Cat_81(String name){
        super(name);
    }
    @Override
    public void printName(){
        System.out.println(name + "だニャン!");
    }
}

//Driver_81.java

public class Driver_81{
    public static void main(String[] args){
        AnimalEmbryo[] animalArray = new AnimalEmbryo[6];
        animalArray[0] = new Dog_81("ヨーゼフ");
        animalArray[1] = new Dog_81("パトラッシュ");
        animalArray[2] = new Dog_81("白いお父さん");
        animalArray[3] = new Cat_81("ニャース");
        animalArray[4] = new Cat_81("ドラえもん");
        animalArray[5] = new Cat_81("ニャンパス");

        //すべての要素で printNameメソッドを実行
        for(int i=0; i<animalArray.length; i++){
            animalArray[i].printName();
        }
    }
}

4つのファイルすべてを wsフォルダに保存して実行します。

コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_81.java
ws>java Driver_81
ヨーゼフだぞ! ワンワン!
パトラッシュだぞ! ワンワン!
白いお父さんだぞ! ワンワン!
ニャースだニャン!
ドラえもんだニャン!
ニャンパスだニャン!

萌えJava超入門 萌えJava超入門
なるほど。
継承さえすれば
普通のクラスなんスね。


7. 抽象クラスはインスタンス化できない

萌えJava超入門
今度はダメなやつ。
ダメと分かりつつ、
抽象クラスをインスタンス化しちゃいましょう。

//Driver_82NG.java
//抽象クラスはインスタンス化できません。
public class Driver_82NG{
    public static void main(String[] args){
        AnimalEmbryo animalEmbryo = new AnimalEmbryo("胚");
    }
}

AnimalEmbryo.java
Driver_82NG.java
を wsフォルダに保存して実行します。

コマンドライン
>cd ws
ws>javac -encoding UTF-8 Driver_82NG.java
ws>java Driver_82NG
Driver_82NG.java:5: エラー: AnimalEmbryoはabstractです。
  インスタンスを生成することはできません
      AnimalEmbryo animalEmbryo = new AnimalEmbryo("胚");
                                  ^
エラー1個

萌えJava超入門 萌えJava超入門
Animal_01クラスはそのまま使うと
「ガオー」。
AnimalEmbryoクラスはそのまま使うと
コンパイルエラーってことね?



萌えJava超入門


8. なぜ抽象クラス?


萌えJava超入門 萌えJava超入門
使い方はザックリわかったわ。
何が良いのか分からないけど。
萌えJava超入門

今の時点では、
「抽象クラス」と「抽象メソッド」というのがあって、
実装しないとインスタンス化できない。

と、ご理解いただければ及第点なのですが、気持ち悪いですよね。

ちょっとだけヒントです。
「クラスの継承」が「ココだけ変えたよ」的なニュアンスなのに対して、
「抽象クラス」は、「ココだけ変えてね」的なニュアンスなんです。

abstract である時点で、実装してほしいメソッドが明確になっていて、
「抽象クラスを作った人」の意図が、使用者に伝わりやすいのです。
抽象メソッドの実装を使用者に預けておきながら、
引数や戻り値が変更できないのもポイントです。
  (この抽象クラスの使い方が決まっている場合に有効。)

これに加えて、その他のメソッドに「final」が付与されていれば、
「抽象メソッド以外は触らないで!!」
的な感じになります。

プログラムを通じて会話しちゃう感じですね。

萌えJava超入門 萌えJava超入門
沼よ!
Javaの沼だわ!
萌えJava超入門


お疲れ様でした。




© 2019 awasekagami