プログラミングを学ぶ中で、関数やクラスの作り方は理解できてきたけど、「抽象クラスってなんで必要なんだろう?」と長らくモヤモヤしていた。
関数との違いに着目してみた
関数って、同じ処理が複数箇所に出てきた時に「共通化しよう」と思って使う。コード量も減るし、実際にその関数を呼び出すから恩恵がすぐに見える。だからこそ「関数化しよう」という意識は自然に持てる。
でも抽象クラスは、定義してもインスタンス化して直接使うことはできない。しかも、クラスの構造を縛るだけ。だから「これ、今作って意味ある?」と感じてしまう。
視点の変換がカギだった
じゃあ、どうやったら「抽象クラスを作ろう」と自然に思えるようになるのか。
例:ArrayListとLinkedList
配列ベースのリスト(ArrayList)と、ポインタベースのリスト(LinkedList)を考えてみると、それぞれにメリット・デメリットがある。
- ArrayList:ランダムアクセスが速い
- LinkedList:挿入・削除が速い
状況によって使い分けたいが、使うときのインターフェース(add, get など)は統一されていた方が使いやすい。
ここで次のような関数を考えてみる。
void processList(MyList list) {
list.add(1);
list.add(2);
System.out.println(list.get(0));
}
この processList
関数は、MyList 型のオブジェクトに対して要素を追加・取得している。重要なのは、この関数が「ArrayListなのかLinkedListなのかを気にせず」使えている点。
これは、MyList
が 抽象クラス(もしくはインターフェース) として、add()
や get()
という共通のメソッドを定義しているから実現できること。
抽象クラスがなかったら?
もし抽象クラス(またはインターフェース)がなかったとしたら、次のようなことが起こります:
-
ArrayList
はaddTo()
、getByIndex()
を使う -
LinkedList
はappend()
、fetch()
を使う
すると、processList
のような汎用的な関数は書けない。以下のように、リストの種類ごとに処理を分ける必要が出てくる。
void processArrayList(ArrayList arrayList) {
arrayList.addTo(1);
arrayList.addTo(2);
System.out.println(arrayList.getByIndex(0));
}
void processLinkedList(LinkedList linkedList) {
linkedList.append(1);
linkedList.append(2);
System.out.println(linkedList.fetch(0));
}
クラスの数が増えるほど、使う側のコードも複雑になってしまう。
抽象クラスで解決!
共通のメソッド名・引数・戻り値の型などを抽象クラスで統一しておけば、実装の中身が違っても使う側は気にせずコードを書ける。
abstract class MyList {
abstract void add(int value);
abstract int get(int index);
}
class ArrayList extends MyList {
// 内部は配列で実装
void add(int value) { /* 実装 */ }
int get(int index) { /* 実装 */ }
}
class LinkedList extends MyList {
// 内部はノードで実装
void add(int value) { /* 実装 */ }
int get(int index) { /* 実装 */ }
}
使う側はこう書ける:
void run() {
MyList list = new ArrayList();
list.add(10);
list.add(20);
System.out.println(list.get(1));
}
このように「使う側」が内部実装を意識せずに済むようになるのが、抽象クラスの大きな恩恵。
利用者視点に立った設計
この経験を通じて感じたのは、「抽象クラスの価値は、クラスを使う側の視点に立つことで初めて実感できる」ということだった。
普段は「作る側」になりがちだけど、実際には「使いやすさ」こそが良い設計を分けるポイント。
この気づきは、今後の設計力を高める上で非常に大事な視点だと感じた。
おわりに
「抽象クラスって意味あるの?」と思っていた自分が、「めちゃくちゃ助かるじゃん!」と実感できたのは、「ちょっとした視点の変換」だった。
物事の見方が変わると、理解速度もぐっと上がる。そう実感した出来事だった。
同じようにモヤモヤしてる人の参考になれば嬉しい。