質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • Java

    14396questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

継承と実装の違い インターフェースについて

解決済

回答 5

投稿

  • 評価
  • クリップ 6
  • VIEW 10K+

extends継承とimplements実装の違いについて質問です

コード
public class Player{
    int winCount;
    Random rnd = new Random();

    public int getPoint(){
        int ran = rnd.nextInt(3);        //0~2ランダム
        return ran;
    }

    public void addWinCount(){
        winCount++;
    }
}
コード
public class Player1 extends Player{

    @Override
    public int getPoint(){
        int ran = 0;

        return ran;
    }
}


継承の場合
上のようなPlayerクラスを継承したPlayer1クラスはgetPointメソッドは上書きされるがaddWinCountメソッドはPlayerクラスと同じように使える

実装の場合
下のようなTacticsクラスを実装したRandomTacticsクラスはreadTacticsメソッドが上書き?されている

私の解釈が間違っているからかもしれませんが、どちらも上書きするだけでそんなに大差が内容に感じます。
継承はPlayerクラスがベースにあって継承することで上書きや処理を追加できるのはわかります。
実装の方はただ上書きするだけのように思います。

いまいちよくわからないのでimplementsの使うべきタイミングやメリットを教えていただきたいです。
まとまりのない文章ですがよろしくお願いします。

コード
public interface Tactics{

    public int readTactics();

}
コード
public class RandomTactics implements Tactics{
    int winCount;
    Random rnd = new Random();

    @Override
    public int readTactics(){
        int ran = rnd.nextInt(3);        //0~2ランダム

        return ran;
    }

    public void addWinCount(){
        winCount++;
    }

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+6

Javaの初心者向けの書籍やサイトでは、インターフェイスの本質的な意味がきちんと説明されていないものが多いですね。まずはインターフェイスの実装とクラスの継承は本質的に異なるということをしっかりと理解しておく必要があります。

英語のinterfaceには「接点」や「仲立ち」、「橋渡し」という意味があります。つまり、インターフェイスというのは、あるオブジェクトと別のオブジェクトの「接点」となる要素ということです。
ここで言う「接点」とは、あるオブジェクトがどのように別のオブジェクトを利用することができるのか?という「仕様」や「規約」と考えることができます。また、「インターフェイスとは契約(contract)である」と言われることもあり、あるクラスが別のクラスに仕事を依頼する際の「決まり事」を定義するためのものであると考えることもできます。

したがって、インターフェイスは、クラスのような「具体的な実装」を提供するものではなく、あくまでも「仕様」や「規約」、「契約」としての役割を提供するためのものだということを理解しておきましょう。

そして、この「規約」や「仕様」、「契約」というのは具体的には、インターフェイスの「型」と「メソッド」によって明示されることになります。

インターフェイスの「型」は「その仕事を遂行できるオブジェクトは何か」という決まり事を表し、メソッドは「何の仕事を依頼できるのか」という決まり事を表します(メソッド名は暗黙的に「何をするか」を表すため、メソッド名は非常に重要です)。さらにメソッドの引数と戻り値の定義は、仕事を依頼する際に「何を渡さなければいけないか」と、その結果「何が返ってくるのか」という決まり事を表しています。

ここで重要なのは、インターフェイスで明示されるのはすべて「何(What?)」であり、具体的な仕事の「どのように(How?)」ではないということです(Howを実装するのはクラスとなります)。

例えば以下のような単純なコードで考えてみましょう。

interface A {
    void doSomething();
}

class X implements A {
    public void doSomething() {
        System.out.println("X");
    }
}

class Y implements A {
    public void doSomething() {
        System.out.println("Y");
    }
}

この例では、Aインターフェイスが「規約」であり、Aという型のオブジェクトはvoid doSomething()という仕事をする、という決まり事(What)だけが定義されています。
そして、クラスXとクラスYは共にAインターフェイスを実装しており、すなわちXとYは、Aで定められた規約の具体的なHowを提供するというわけです。

これらのコンポーネントを利用する側のクラスとして以下のようなZクラスを考えてみましょう。

public class Z {

    public void method(A obj) {
        obj.doSomething();
    }
}


このZクラスのmethodを呼び出す場合、引数で定義されているA型であればどのようなオブジェクトでも渡すことができます。A型の契約を締結しているオブジェクトはdoSomethingメソッドを提供していることが保証されているからです。したがって、具体的にどのようなオブジェクトが渡されようとも(XでもYでもOK)、それがA型という規約を守っているのであれば、そのオブジェクトのdoSomethingメソッドを呼び出して正常に処理することができるという保証が生まれます。
それに対してA型を実装していない、つまりAという契約を締結していない他のオブジェクトは渡すことはできません。doSomethingメソッドが実装されている保証がないからです。

このようにインターフェイスというのは、あくまでも、あるオブジェクトと別のオブジェクト間の「仕事の依頼」に関する「決まり事」をコードとして明示するためのものであり、「クラスの継承」とは本質的に異なるものだということです。つまり「クラスの継承」は、既に実装された機能を再利用するための仕組みであるのに対して、「インターフェイス」はライブラリの「設計」における決まり事を定めるために重要だということです。
インターフェイスを一切使用しなくてもライブラリを設計・実装することは可能ですが、インターフェイスをうまく活用することで、汎用性や拡張性、保守性に優れたライブラリを設計することができるようになります。なので、JDKなどのライブラリにはインターフェイスがたくさんありますが、それらを利用するコードを書く場合には自分でインターフェイスを作成する必要性はあまりありませんよね?

インターフェイスを活用した設計としてデザイン・パターンと呼ばれるセオリーがあるので、興味があれば勉強してみてください。より理解が深まると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/25 16:26

    回答ありがとうございます!
    継承と実装は全然違うものだったんですね!
    わかりやすくて掴めた気がします
    ありがとうございました!

    キャンセル

+1

・継承について
「旧型マウス」と「新型マウス」を想像してください。
1-旧型マウスはクリックするとPCにクリック情報を伝えます。
2-新型マウスはクリックすると旧型マウスの機能に加え、クリックした強さを伝えます。

この時、「旧型マウス」と「新型マウス」を継承関係にすると「新型マウス」ではクリックした強さに関する実装だけを新規に作るだけで良くなります。

・実装について
「人間」と「マウスのボタン」と「PCのボタン」を想像してください。
1-「人間」はボタンを押すことができます。
2-「マウスのボタン」は押されることができます、このときクリックが発生します。
3-「PCのボタン」は押されることができます、このときPCの電源が付きます。

この時、「押された時の処理」をインターフェースにしておくことで「人間」は「押された時の処理」が実装されているもの「押す」ということができます。また、押したものがマウスのボタンなのか、PCのボタンのボタンなのかを識別しなくても良いところに利点があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/23 17:45

    回答ありがとうございます。
    継承はベースのクラスから一部機能を追加変更したいときに使う
    実装は公式みたいに「押された時の処理」というのを作っておいて、マウスのボタンでも使える、PCのボタンでも使えるみたいな感じですかね?

    キャンセル

  • 2017/03/23 17:52

    最初の理解としては十分だと思います、慣れた頃に再度調べたらいいですよ。

    キャンセル

  • 2017/03/25 16:19

    ありがとうございました!
    掴めた気がします!
    また調べてみたいと思います。

    キャンセル

0

C++のような一部の例外を除いて、Javaなど多くの言語では基底クラスは1つしか持てません。一方で、インターフェースは(メソッドが干渉するなどの事情がなければ)1つのクラスにいくつでも実装できます。

そのため、「特定のメソッドが呼べればいい」と言うかたちでいろんなクラスを共通して扱いたい場合は、継承でやらずにインターフェースとしたほうが、基底クラスを固定せずに済むので便利です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/23 16:38

    回答ありがとうございます!
    継承は1つ、実装は複数できるというのは知っていましたが、
    継承と実装の違いはそこだけということでしょうか?

    キャンセル

0

どの本を見ても、継承から先に取り扱っているので誤解されやすい点だと思いますが、多態と継承は分けて考えるべきです。(多態はとりあえず、複数の型を基底クラスまたはインターフェイスクラスの変数として扱うためにあるとと考えてください。)

継承のみでも多態を使うことができますが、単一継承の制約の制約を抜きにしても、多態は実装とは結びつける必要はありません。

そのため、継承もインターフェイスを保証できるため”おまけ”として多態ができると考えておくと考え方はスッキリすると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/25 16:26

    回答ありがとうございます!

    キャンセル

-1

継承と実装の違いについて、へんな例えになりますが例え話を書きます。

とある特殊部隊はビームが打ててロケットパンチが打てるパワードスーツを着ていることが出動条件となっています。

ベーシックパワードスーツはすでに完成しており、これを着るだけで特殊部隊の隊員になれますし、ビームも打ててロケットパンチが打てます。

隊員Aはベーシックパワードスーツをそのまま使います。これでビームもロケットパンチも打てます。

隊員Bはベーシックパワードスーツのビームを改造して、青色のビームが出るようにしました。ロケットパンチはベーシックなままです。

隊員Cはベーシックパワードスーツのロケットパンチを改造して、スピードをあげました。ビームはベーシックなままです。

隊員Dはなんとパワードスーツの規格に則って、自分でスーパーパワードスーツを作りました。ベーシックなものとビームとロケットパンチの性能は違いますが、特殊部隊の出動条件をきちんと満たしています。

着ているパワードスーツは全員違っても、全員ビームもロケットパンチも打てるので隊員として扱うことができます。

以上の話で、継承と実装を説明するのであれば、以下のようになります。

継承:隊員B、隊員Cのように、既存のパワードスーツをカスタムする
実装:隊員Dのように、自分で規格に則って作る

追記

ある日、「特殊部隊隊員はパワードスーツに通信機器を取り付けること。本部と通信が出来ればなんでもよい」という通達がありました。隊員は各々パワードスーツを改造します。元々ベーシックパワードスーツには通信機器がないので、自分たちで取り付けることになりました。

隊員Aさんはスマホを取り付けました。
隊員Bさんはトランシーバーを取り付けました。
隊員Cさんはガラケーを取り付けました。
隊員Dさんは衛星電話を取り付けました。

全員、元々パワードスーツにそんな機能はありませんでしたが、本部と意思疎通は可能になりました。使っているものはバラバラですが、目的は果たしています。

これが実装の利点です。使う側が「この要件を満たして欲しい、でもこちらからはなにもベースになるものは出さない」状態でも、インタフェースというルールさえ実装すれば、ちゃんとお互い目的を果たすことができるのです。

例えばJavaのよく使われるインタフェースとしてjava.lang.Iterableというものがあります。

List<Integer> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();
Queue<Integer> queue = new ArrayBlockingQueue<>();


ListとSetとQueueは動作する振る舞いはすべて違いますが、これらはすべてIterableを実装しています。Iterableを実装していると、拡張forに使えます。

for(Integer int : list) {
}
for(Integer int : set) {
}
for(Integer int : queue) {
}


Iterableは「順番に要素を取り出せること」という要件が記述されているため、Iterableさえ実装したクラスであれば、forの処理で共通して使えることが保証されているのです。インタフェースとは「その機能を持っていることを保証するよ」という証明なのです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/23 17:36

    回答ありがとうございます。
    この話でいくと隊員Aをスーパークラスとして
    BにAを継承してビームメソッドをオーバーライド
    CにAを継承してロケットパンチメソッドをオーバーライド
    DにAを継承して両方のメソッドをオーバーライド
    したらいいと思ってしまうのですが、Dは実装になるんですかね?

    キャンセル

  • 2017/03/23 17:51

    それでも十分問題ないです。ちょっと例えが悪かったですね。追記します。

    キャンセル

  • 2017/03/25 16:17

    追記載せていただいてありがとうございます!
    感覚的にですが掴めた気がします!
    ありがとうございました。

    キャンセル

同じタグがついた質問を見る

  • Java

    14396questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。