クラスの継承
抽象クラス
中身が無いメソッドを持つ不完全なクラス
abstract
目次
1. 抽象クラス
抽象クラスには、必ず abstract 修飾子 を付与します。
(アブストラクトって読みます。)
抽象メソッドって
なに?
2. 抽象メソッド
抽象メソッドにも、必ず abstract 修飾子 を付与します。
メソッドの中身の部分「{}」(波カッコ)は書かずに、
そのまま「;」(セミコロン)で閉めます。
引数や戻り値の記述は必要です。
尚、「()」(丸かっこ)があることで、メソッドであることを示しています。
注: クラスメソッド(staticメソッド)を 抽象メソッドにすることはできません。
え?
こんなのあり?
3. 実装とは
とりあえず
言葉だけ覚えよう。
実装とは
- メソッドの中身の部分「{}」(波カッコ)の中を「メソッドの実装」といいます。
- 「実装する」のように、動詞的な使い方をすることもあります。
その場合、「{}」の中を記述する意味で使います。
言葉の使用例:
抽象メソッドとは、実装されていないメソッドのことです。
抽象クラスは、サブクラスで抽象メソッドを実装してから使います。
- インターフェースを implements することも、「実装する」といいます。(後述)
この辺は
そんなに厳密じゃない。
言葉の使い分け
「オーバーライドする」は、
すでに実装されているメソッドの書き換えのニュアンスが強いです。
「実装する」は、
抽象メソッド(実装が空)に処理を記述する時に使います。
書き換える事を「実装する」とはあまり言わないのに対して、
「オーバーライドする」は、抽象メソッドに処理を記述する場合でも使います。
3. 抽象クラスは不完全なクラス
抽象クラスは、一部のメソッドの処理内容が書かれていない、不完全なクラスです。
このため、抽象クラスはインスタンスを生成することができません。
抽象クラスを継承して、サブクラスを使いましょう。
すべての抽象メソッドを実装すると、普通のクラスとして使用できます。
すべてのメソッドが実装されたクラスは「具象クラス」と呼ぶことがあります。
実装していないメソッドがあるサブクラスも、抽象クラスになります。
やっぱり
そのままでは
使えないんですね。
5. 抽象クラスのテンプレ
↓↓↓ AbstClass01クラスの継承 ↓↓↓
extendsで継承するのは
普通のクラスと同じっスね。
「subClass」は普通のクラスとして
利用することができるぞ。
6. 抽象クラスの継承サンプル
以下のAnimalEmbryoクラスは、
printNameメソッドを抽象メソッドに持つ抽象クラスです。
//AnimalEmbryo.java
//抽象クラス
public abstract class AnimalEmbryo{
protected String name;
public AnimalEmbryo(String name){
this.name = name;
}
public abstract void printName(); //抽象メソッド
}
前述の Animal_01クラスでは
printNameメソッドで「ガオー」
と表示されたが、
AnimalEmbryoクラスでは
抽象メソッドだ。
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
ヨーゼフだぞ! ワンワン!
パトラッシュだぞ! ワンワン!
白いお父さんだぞ! ワンワン!
ニャースだニャン!
ドラえもんだニャン!
ニャンパスだニャン!
なるほど。
継承さえすれば
普通のクラスなんスね。
7. 抽象クラスはインスタンス化できない
今度はダメなやつ。
ダメと分かりつつ、
抽象クラスをインスタンス化しちゃいましょう。
//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個
Animal_01クラスはそのまま使うと
「ガオー」。
AnimalEmbryoクラスはそのまま使うと
コンパイルエラーってことね?
8. なぜ抽象クラス?
使い方はザックリわかったわ。
何が良いのか分からないけど。
今の時点では、
「抽象クラス」と「抽象メソッド」というのがあって、
実装しないとインスタンス化できない。
と、ご理解いただければ及第点なのですが、気持ち悪いですよね。
ちょっとだけヒントです。
「クラスの継承」が「ココだけ変えたよ」的なニュアンスなのに対して、
「抽象クラス」は、
「ココだけ変えてね」的なニュアンスなんです。
abstract である時点で、実装してほしいメソッドが明確になっていて、
「抽象クラスを作った人」の意図が、使用者に伝わりやすいのです。
抽象メソッドの実装を使用者に預けておきながら、
引数や戻り値が変更できないのもポイントです。
(この抽象クラスの使い方が決まっている場合に有効。)
これに加えて、その他のメソッドに「
final」が付与されていれば、
「抽象メソッド以外は触らないで!!」
的な感じになります。
プログラムを通じて会話しちゃう感じですね。
沼よ!
Javaの沼だわ!
お疲れ様でした。