まず質問の
インターフェースを実装(implements)するということは、親クラスがインターフェースのクラスになるということなのでしょうか。
については違います。
順を追って説明します。
インターフェースについて
インターフェースは名前の通り、クラスのインターフェースを定義するための物です。
これには具体的な実装方法は含みません。
プログラミング以外でもこの概念は使われていて、
たとえば標準的なマウスであれば、
- カーソルの移動ができる
- 左クリックができる
- 右クリックができる
- スクロールができる
というインターフェースを持っていることになります。
ソースに起こすならこんな感じですね。
interface Mouse {
/**
* カーソルを移動します。
* @param x 左右の移動量
* @param y 上下の移動量
*/
public void move(Integer x, Integer y);
/**
* 左クリックを行います。
*/
public void leftClick();
/**
* 右クリックを行います。
*/
public void rightClick();
/**
* スクロールを行います。
* @param amount スクロールする行数
*/
public void scroll(Integer amount);
}
}
マウスの中の具体的な実装(implement)はメーカーや商品によって異なりますが、
インターフェースが同じであるため、どのマウスでも同じように扱うことができますよね。
ソースに起こすならこんな感じですね。
/**
* 普通のマウス
*/
class NormalMouse implements Mouse {
public void move(Integer x, Integer y){
// 赤外線を使ったりなんやかんや
};
// 他の実装は割愛
}
/**
* 古いマウス
*
* ※下に球が入っていてそれの転がりで移動を検出する!
* ※球だから掃除しないと動きづらくなったりする…
*/
class OldMouse implements Mouse {
public void move(Integer x, Integer y){
// 球の転がりを検出したりなんやかんや
};
// 他の実装は割愛
public void cleaning(){
// ボールの掃除など…
}
}
この時NormalMouseやOldMouseは、Mouseを実装しているだけで親クラスはありません。
中の仕組みが違ったり分からなかったりしても「マウス」というインターフェースを知っていればマウスは使えます。
インターフェースというのは、「こう動かすとこういう結果になりますよ。」という使い方だけを表しているわけですね。
そしてJavaではinterfaceをimplementするということは、「このクラスはこのinterfaceで使えますよ」ということを保証していることになります。
※interface内の要素を一つでも実装していないとコンパイルエラーになります。
ですので、「マウス使いたいからちょっと貸して!」と言っている人がいたとして、
普通のマウスを渡しても古いマウスを渡してもどちらでも問題ないわけです。
ソースに起こすならこんな感じですね。
public class UseMouseTest {
public static void main(String[] args) {
Mouse mouse = new NormalMouse();// new OldMouse(); でも問題ない!
useMouse(mouse);
}
public useMouse(Mouse mouse){
// 左クリックしたりなんやかんや…
mouse.leftClick();
}
}
またもし「古いマウスでもちゃんと動くか試したいから貸して!」と具体的な実装を指定している人であれば古いマウスを渡さなくてはいけません。
public class UseMouseTest {
public static void main(String[] args) {
OldMouse oldMouse = new OldMouse();// new NormalMouse(); ではだめ!
oldMouseTest(oldMouse);
}
public oldMouseTest(OldMouse oldMouse){
// 左クリックしたりなんやかんや…
oldMouse.leftClick();
// 掃除もする…
oldMouse.cleaning();
}
}
継承について
インターフェースの例を引き継いで説明します。
通常のマウスの機能に加えて、サイドボタンが追加されているマウスなどを作りたい場合もあります。
こういう場合は継承することで、追加の機能のみの開発で済ませることができます。
ソースに起こすならこんな感じですね。
/**
* サイドボタン付きのマウス
*
* 普通のマウスの機能を持っている!
* 戻る と 進む もできる!
*/
class SideButtonMouse extends NormalMouse {
/**
* 戻るボタン
*/
public void back() {
// 戻る
}
/**
* 進むボタン
*/
public void forward() {
// 進む
}
}
このときSideButtonMouseはNormalMouseのサブクラス(または子クラス、派生クラス)であり、
NormalMouseはSideButtonMouseのスーパークラス(または親クラス、基底クラス)です。
継承で守らないといけない大事なルールとして、リスコフの置換原則
があります。
簡単に言うと「サブクラス is スーパークラス」です。
今回の例では「サイドボタン付きのマウス は 普通のマウス である」ですね。
サブクラスはスーパークラスとしても使えなければなりません。
そして
「SideButtonMouseはNormalMouseである」
「NormalMouseはMouseを実装している」
ということは、
「SideButtonMouseはMouseを実装している」
ということになります。
まとめ
ここまでのそれぞれのクラス・インターフェースを使って関数を作るとこんな感じです。
/**
* マウスを使う
*
* NormalMouse, OldMouse, SideButtonMouseすべてOK
*/
public useMouse(Mouse mouse){
mouse.move(2, 3);
mouse.leftClick();
mouse.rightClick();
mouse.scroll(2);
}
/**
* 古いマウスを使う
*
* OldMouseのみOK
*/
public useOldMouse(OldMouse mouse){
mouse.move(2, 3);
mouse.leftClick();
mouse.rightClick();
mouse.scroll(2);
mouse.cleaning();
}
/**
* 普通のマウスを使う
*
* NormalMouse, SideBUttonMouseならOK
*/
public useNormalMouse(NormalMouse mouse){
mouse.move(2, 3);
mouse.leftClick();
mouse.rightClick();
mouse.scroll(2);
}
/**
* サイドボタン付きのマウスを使う
*
* SideBUttonMouseのみOK
*/
public useSideButtonMouse(SideButtonMouse mouse){
mouse.move(2, 3);
mouse.leftClick();
mouse.rightClick();
mouse.scroll(2);
mouse.back();
mouse.forward();
}
また上の例では「古いマウス」や「サイドボタン付きのマウス」はクラスとして記述しましたが、
実際はこれもインターフェースにして実装と分けほうが良かったりもします。
インターフェースでは他のインターフェースを継承することができますので、
このようにできます。
interface SideButtonMouse extends Mouse {
/**
* 戻るボタン
*/
public void back();
/**
* 進むボタン
*/
public void forward();
}
interface MySideButtonMouse extends NormalMouse implements SideButtonMouse {
public void back() {
// 戻る
};
public void forward() {
// 進む
}
}
こうすることで実装に影響されない「サイドボタン付きのマウス」を表現できます。
長々となってしまいましたが、参考になれば幸いです。