はじめてのJava ~抽象クラスとインタフェース編~
スポンサーリンク
今回はJavaの抽象クラスとインタフェースについて説明します。
この2つはとても似ている機能なので、まとめて紹介します。
初心者が混同しやすいこの2つですが、使える場面が異なります。
抽象クラスとインタフェースはなぜ必要なのか
前回、継承について説明したときは、継承することによってコードを効率的に再利用できると言いました。
しかし、これが別のプロジェクトになったらどうなるでしょうか?
メソッドの名前が同じでも中身が同じとは限りません。
例を挙げて考えてみましょう。
とある企業Aは3つのプロジェクトを同時進行しています。
その3つのプロジェクトはコードの再利用が可能であることがわかりました。
優秀なプログラマBさんは、いずれでも使うと思われるClass1クラスを作っておくことにしました。
Class1クラスではとある計算をするcalc()メソッドを定義します。
しかし、詳細は未定であるためメソッドの中身までは実装できません。
そこでメソッドの中身を空にしておくことにしました。
class Class1 { void calc() { } }
数日後、それぞれのプロジェクトが進行し、どちらも開発フェーズに入りました。
プロジェクト1にアサインされている適当プログラマCさんはClass1 のコードを見てこう思います。
「このメソッドはなにもしないメソッドなんだ」
詳細が決定してから実装するはずであった箇所を、Cさんは勘違いして無視してしまいました。
また、プロジェクト2にアサインされている多忙プログラマDさんは設計書をよく読んだので、Class2クラスでClass1クラスを継承し、calc()メソッドをオーバーライドしなくてはいけないことを知っています。
しかし、疲れからかオーバーライドするのを忘れてしまいました。
さらにプロジェクト3にアサインされている新人プログラマEさんは、Class1クラスを以下のように使いました。
class Main1 { public static void main(String args[]) { Class1 c1 = new Class1(); // 以下省略 } }
いまいち継承の使い方がわからず、インスタンスを作ってしまいました。
これらのような失敗を起こさないため、抽象クラスやインタフェースを使います。
それでは、それぞれの使い方を見ていきます。
抽象クラスの使い方
abstract class Animal { abstract void walk(); }
classの前に「abstract」を付けます。
class Dog extends Animal { void bark() { System.out.println("ワン"); } }
// エラーメッセージ Dog.java:1: エラー: Dogはabstractでなく、Animal内のabstractメソ ッドwalk()をオーバーライドしません class Dog extends Animal { ^ エラー1個
しっかりエラーが出ました。
これでCさんとDさんの失敗は解決できたことがわかります。
次に、Animalクラスをインスタンス化してみます。
class AnimalMain { public static void main(String args[]) { Animal dog = new Animal(); } }
// エラーメッセージ AnimalMain.java:3: エラー: Animalはabstractです。インスタンスを 生成することはできません Animal dog = new Animal(); ^ エラー1個
こちらもエラーになり、Eさんの失敗は解決しました。
インタフェースの使い方
では、インタフェースはどのようなときに使うのでしょうか?
抽象クラスに対するインタフェースの特徴は多重継承できる点です。
WolfクラスとHumanクラスを継承した狼人間はどのように動くのでしょうか?
両方から異なる動作のmove()メソッドを継承するため、不具合が起きてしまいます。
オーバーライドによって独自のmove()メソッドを実装することができます。
これで多重継承の問題は解決です。
それではインタフェースの使い方を見ていきましょう。
interface Wolf { void move(); }
interface Human { void move(); }
class WolfMan implements Wolf, Human { public void move() { System.out.println("walk:bipedal, run:quadruped"); } }
class WolfManMain { public static void main(String args[]) { WolfMan wm = new WolfMan(); wm.move(); } }
// 出力 walk:bipedal, run:quadruped
インタフェースには「interface」を付け、実装側では「implements」で使用するインタフェースを明示します。