抽象クラスとインターフェース
抽象クラス
抽象クラスとは、クラスの継承関係の考え方をより抽象的にしたものです。継承関係をより抽象的に表現したクラスのことです。継承されることが前提で定義され、abstractキーワードを使います。
Animalクラスを例にしてみます。
たくさんの動物がいる中で、吠え方を1つ特定するようなことができません。そのため、宣言だけを記述します。メソッドの中身を書きようがないのです。
抽象メソッドには、abstractキーワードを使用します。
抽象クラスAnimalを継承したDogクラスは、メソッドをオーバーライドする必要があります。
Animalのような具体的な処理を表現できない抽象的なクラスを「抽象クラス」と言います。
インターフェース
インターフェースとは、「抽象クラスの概念を強くしてメソッドの実装すらできなくしたもの」です。抽象クラスAnimalのメソッドには中身を実装していませんが、抽象メソッド以外に、具体的な内容のあるメソッドを定義することも可能です。これを具象メソッドと言います。
例えば、歩くとか食べるとか寝るなどのメソッドです。
でも、インターフェースは具象メソッドを実装することができないのです。
Java8からdefaultメソッドとstaticメソッドの実装が可能になりましたが、本講座では扱いません。
クラスの規格のみを定義したものです。classキーワードの代わりにinterfaceと記述します。継承の解説で使用していた有線のイヤホンと、AirPodsのようなワイヤレスイヤホンを例にしてみます。
イヤホンをインターフェースすると以下のようになります。
ワイヤレスイヤホン(Earbuds)は以下のようになります。
クラスの継承の際には、というキーワードを使いますが、インターフェースの場合はというキーワードを使います。メソッドはオーバーライドする必要があります。これを「インターフェースを実装する」と言います。
でも、この例はインターフェースとそれを実装したクラスにはあまりふさわしくありません。なぜならEarphoneクラスのメソッドとメソッドは処理の中身に相当する機能があり、規格にはならないからです。
なので、別の名前のAudioAccesoryというものにしてみました。
Earphonesクラスはインターフェースとしていましたが、AudioAccesoryを実装したクラスに変更しました。
EarbudsがするのもAudioAccesoryインターフェースです。AudioAccesory規格を実装しています。
新しいクラスが生まれるかもしれません。それは"Headphones"(ヘッドホン)という名前で、AudioAccessoryインターフェースを実装します。
機器にBluetoothで接続することもあるでしょう。そのような場合は、Headphonesクラスを継承したWirelessHeadphonesクラスを作って、connectメソッドをオーバーライドすると良いでしょう。
抽象クラスとインターフェースの違い
抽象クラスに相応しくないクラス
introduceというメソッドを持った、Personクラスがあるとしましょう。
メソッドは、自己紹介をするメソッドです。
また、Personクラスを継承したStudentクラスがあるとしましょう。
メソッドをオーバーライドしています。
Personクラスのメソッドは必ずオーバーライドされる前提なら、メソッドの中身が実装されている必要はありません。
でも、Personクラスをabstractにして抽象クラスにするのはふさわしくありません。
Personクラスは「はじめまして…」と自己紹介する具体的な処理があるからです。
では、抽象クラスにはどのような親子関係になるクラスがふさわしいのでしょうか?
抽象クラスに相応しいクラス
ポリモーフィズムの解説で例にした、メソッドを持つAnimalクラスとそれを継承したDogクラスとWolfクラスの場合、Dogは「ワンワン」、Wolfは「ワォーン」と吠えます。では、Animalはどのように吠えるのでしょうか?
DogとWolfのメソッドには具体的な処理をかけるのですが、動物全般を表すようなクラスAnimalのメソッドには具体的な処理が書けないのです。
抽象クラスの使い所
抽象クラスに相応しいクラスとは、「抽象的で概念を示したもの」です。
「クラスを概念でグループ化したいような時」に使います。
is a 関係
ここで少し「is a 関係」という言葉について触れておきたいと思います。継承の解説でよく登場する表現なのですが、「〜は〜の一種である」という意味になります。
- DogはAnimalの一種である
- WolfはAnimalの一種である
というような時に使います。継承関係にある親子クラスは「is a 関係にある」といいます。
インターフェースの使い所
インターフェースは、クラスとは全く違うものです。メソッドをオーバーライドしますが、クラスの継承とは違う意味を持ちます。それは、親の機能を引き継がないからです。
では、一体なんなのでしょうか?
- クラスの規格
- 雛形
- テンプレート
- ルールブック
などとよく例えられます。つまり「is a 関係にない」ということです。
Javaでは、クラスの多重継承ができません。多重継承とは、複数の親クラスから子クラスを作ることを指します。しかし、Javaではこれができません。それでも、何らかの理由で多重継承をしたい時があります。
例えば、ポリライン(線)、三角形、円といったクラスがあるとしましょう。いずれも、描くというメソッドを持っています。
シェイプ、図という抽象クラスを継承するのがふさわしいでしょう。
ここに、ポリゴン(多角形)というクラスが登場するとします。三角形、円、ポリゴンクラスは線が閉じられているので、面積を求めることができます。というメソッドを持っています。
閉じられたシェイプインターフェースを実装しているのがふさわしいでしょう。
- ポリライン(線)クラス
- 1つのクラスを継承
- 三角形クラスと円クラス
- 1つのクラスを継承
- 1つのインターフェースを実装
- 多角形クラス
- 1つのインターフェースを実装
ということになります。
インターフェースは、継承関係にないクラスを束ねたい(分類したい)時に使います!