プログラミング応用a 第13回 『抽象クラス・抽象メソッド1』 13-5. 抽象メソッドと抽象クラス |
【13-5. 抽象メソッドと抽象クラス】〜 抽象度の高いクラスの問題
・前述したRPGキャラクターと交通シミュレーションの例の様に,
スーパークラスとして作られた様な抽象性の高いクラスでは,具体的な振る舞いが定義できず,それがトラブルを引き起こすことがある。
→そのためJavaでは,そのような抽象度の高いクラスは,実装部(具体的な振る舞いの定義)の無いメソッド(抽象メソッド)を定義することができるようになっている(Fig.4-(1))。
そして,抽象メソッドを持つクラスを抽象クラスとして指定し,そのクラスのオブジェクトの生成を禁止している(Fig.4-(2))。
こうして,
『具体的な振る舞いが定義できないクラスのオブジェクトが生成されて問題を起こす』というトラブルを回避しているのである。
下図に,抽象メソッドと抽象クラスの定義方法と性質を示す。
下図は,抽象メソッドがサブクラスに継承されてオーバライドされ,普通のメソッドになる様子を表している。
このように,
抽象メソッドをオーバライドするということ → シグネイチャだけの抽象メソッド(言わば不完全なメソッド)に,ボディ部分を与えて普通のメソッドにすること
なのである。(下図の説明をひととおり確認したら,図をクリックして次の図を表示させその内容も確認すること。)
スーパークラスから継承した抽象メソッドを,サブクラスでオーバライドし忘れると,そのサブクラスは抽象クラスとして定義しなくてはならなくなる。
実際の例を見てみよう。下図の List 5 では,抽象クラス A の2個の抽象メソッドを
・サブクラスB1の場合: 両方ともオーバライドした。その結果,B1にはもう抽象メソッドは残っていないので,B1は普通のクラスになれた。 → B1のオブジェクトを生成できる。
・サブクラスB2の場合: am1( )だけオーバライドした。その結果,B1にはまだ抽象メソッド am2( )が残っているので,B2は抽象クラスのまま。 → B2のオブジェクトは生成できない。
となっている。
List 5
抽象クラスを使って,交通シミュレーションの例を書き直すと次の様になる。
スーパークラス Vehicle を抽象クラスにし, move( ) メソッドを抽象メソッドとして定義している。
これにより, Vehicle 型オブジェクトの生成が禁止されるので,エラーとなる(List 6-⑤)。
もうこれで, Vehicle型オブジェクトが悪さをすることはない,ということになる。
List 6
【コラム】なぜ,抽象クラスはオブジェクトの生成が禁止されるのだろうか。
もちろん,『抽象クラスには具体的な処理が定義できない抽象メソッドが含まれていることが多く,オブジェクトを生成すると問題を起こすから』
なのだが,
・『クラスはオブジェクトの設計図』
という基本に立ち返れば,
・『抽象メソッドはボディの欠けた不完全なメソッドで,それを含むクラスは,設計図としては穴が空いてしまった未完状態と言える。
未完成の設計図(抽象クラス)から製品であるオブジェクトを生成することはできない。』
という事が言える(下図)。
皆さんも,大事なところに穴の空いた設計図を渡されて「これ作れ」って言われても,困りますよね?
とにもかくにも,Javaのシステムは abstract と指定されたクラスがあれば,それをオブジェクトの設計図としては不完全とみなして,オブジェクトの作成が不可能と判断する。
というわけで,抽象クラスのオブジェクトが作成できないのはごく自然なことなのである。
【まとめ】
このように,スーパークラス用に書かれたクラスは,実はほとんどが抽象クラスとして定義されることになる。
コツとしては,
『サブクラスを作ることを前提としたスーパークラス用のクラスは,抽象クラスとして定義せよ。
そして,そのクラスのメソッドのうち,具体的な処理が想定できないメソッドは抽象メソッドにせよ。』
となる。