抽象クラス


今回は抽象クラスについてみていきます。

抽象とは

抽象という意味を「goo辞書」で調べてみました。

事物や表象を、ある性質・共通性・本質に着目し、それをひき出して把握すること

反対語をみてみると「具体」とあったので簡単にいえば

抽象とは具体的でないこと

プログラムでのイメージをつかめればいいのでこの程度の理解でいいでしょう。
では何が具体的でないのか詳しくみていきます。

java087

(1)動物ロボットの設計図

動物ロボットの共通的性質や機能を集めた設計図です。動物ロボットには「寝る」という機能と「鳴く」という機能をつけます。「寝る」という機能は犬や猫でも共通プログラムとして設計できたとします。しかし「鳴く」という機能は、犬は「ワンワン」と鳴き、猫は「ニャンニャン」と鳴き異なります。そこで「鳴く」という処理は、設計を書く枠だけ準備しといて具体的な処理の内容は犬ロボット担当者や猫ロボット担当者に任せるとします。どんな鳴き方かは全く示さないで、とりあえず「鳴く」という機能がほしいと抽象的に書いています。未完成な設計図だといえます。

(2)犬ロボット、猫ロボットの拡張設計

動物ロボットの設計図は未完成でした。「鳴く」機能の設計が書かれていません。そこで犬ロボットと猫ロボットの担当者が「鳴く」機能について具体的な設計を記述します。これはベースとなる設計図の機能を変更するとも考えることができます。このような考えは「オーバーライド」で記事にしたのでこちらを参考にしてください。

(3)設計図の見方

設計図にはベースとなる部分が書かれたものと、変更(具体的記載)が書かれたものがあります。実際にロボット製作するときは当然両方の設計図をみて作成します。上図では、「寝る」という機能は犬ロボットと猫ロボット共通ですが、「鳴く」という機能は犬は「ワンワン」、猫は「ニャンニャン」と異なります。

サンプル

【Animal.class】

abstract class  Animal{
	// 寝る(通常メソッド)
    void sleep(){
    	System.out.println("寝ています ZZzz…");
    }
	// 鳴く(抽象メソッド)
	abstract void bark();
}

java088

動物ロボットの共通機能を集めた設計図です。「sleepメソッド(※寝る)」には具体的な処理が書かれていますが「barkメソッド(※鳴く)」には何も処理が書かれていません。「鳴く」という処理は犬ロボットや猫ロボットで処理内容が異なるのでここでは何も記述せず、とりあえず「鳴く」という機能がほしいと抽象的に書いています。「barkメソッド(※鳴く)」は必ず犬ロボット担当者や猫ロボット担当者に具体的な処理を書いてもらわないといけないので合図が必要です。そこで抽象メソッドであることを示すためメソッド名の前に「abstract」と記述します。

abstract 返却値の型 メソッド名 (引数・・・) {}

これで継承先である犬ロボットクラスや猫ロボットクラスは「barkメソッド(※鳴く)」を記述しないと設計図が未完成のままであるためインスタンス化できなくなります。
また、このクラスは未完成であると合図しておきます。合図は同じで「abstract」です。

abstract class クラス名 { ・・・ }

このように抽象メソッドを含むクラスを抽象クラスといいます。

【Dog.class】

class Dog extends Animal{
	// 鳴く
	void bark(){
		System.out.println("ワンワン");
	}
}

【Cat.class】

class Cat extends Animal{
	// 鳴く
	void bark(){
		System.out.println("ニャンニャン");
	}
}

java089

DogクラスとCatクラスは抽象クラスであるAnimalクラスを継承しています。抽象クラスは未完成な設計図でした。そこで具体的処理の書いていない抽象メソッドをオーバーライドして処理を記述します。これで全ての機能の処理が書かれ設計図が完成しました。

【Sample.java】

public class Sample {
    public static void main(String[] args) {
    	Dog dog_robot = new Dog();
    	Cat cat_robot = new Cat();

    	dog_robot.sleep();
    	dog_robot.bark();
    	cat_robot.sleep();
    	cat_robot.bark();
    }
}
寝ています ZZzz…
ワンワン
寝ています ZZzz…
ニャンニャン

完成した設計図ができればインスタンス化ができます。ここまでの処理の流れは「オーバーライド」と同じです。抽象クラスにすることにより「オーバーライド」を強制的にしています。

抽象クラスからインスタンスを生成できない

public class Sample {
    public static void main(String[] args) {
    	Animal robot = new Animal();
    }
}
Exception in thread "main" java.lang.Error:
                     Unresolved compilation problem:
	型 Animal のインスタンスを生成できません

抽象クラスからインスタンスを生成してみます。結果はエラーになります。抽象クラスは未完成な設計図でした。設計図が完成していないのですからその設計図から物をつくることはできません。

抽象メソッドをオーバーライドしない場合

class Dog extends Animal{
}
Exception in thread "main" java.lang.Error:
                     Unresolved compilation problem:
	型 Dog は継承された抽象メソッド Animal.bark() を
        実装する必要があります

抽象クラスを継承して抽象メソッドをオーバーライドしない場合、エラーになります。このDogクラスには「abstract」がないので完成した設計図を表します。しかし抽象メソッドをオーバーライドしていないので具体的な処理が書かれていないメソッドが残っています。完成したと言っておきながら未完成要素が残っているのでエラーになります。このDogクラスも抽象クラスにすればエラーになりません。未完成なクラスと言っているので未完成要素が含まれていても問題ありません。最終的に未完成要素がなくなればOKです。


[java クラス 関連記事]

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です