インターフェイスと抽象クラスの違いは何ですか?


1753

インターフェイスと抽象クラスの違いは何ですか?


96
これは非常によくあるインタビューの質問です。抽象クラスが他のものと比較してソリューションで使用されることはめったにないので、それは驚くべきことです。あなたの質問は私にサフラズを助けました。
Catto 2014

5
この質問は、ヘルプには、インタフェースの概念を理解するかもしれないstackoverflow.com/q/8531292/1055241
gprathour

6
この質問からPHPタグを削除しました。答えはほとんど言語固有ではなく、質問自体は言語固有ではないためです。
ブライス

2
昔のc ++では、インターフェイスはすべてのメソッド実装= 0の純粋な抽象基本クラスです。単一のメソッドが= 0でない場合、そのメソッドには実装があり、抽象基本はもはや純粋ではなく、インターフェイスではありません。多重継承が純粋な抽象ベースのみを使用する場合、VMTは間接性が少ないと思いますが、それらがどのように見えるか覚えていません。長すぎます。
ジム

回答:


2255

インターフェース

インターフェースはコントラクトです:インターフェースを書いている人は「ねえ、私はそのように見えるものを受け入れます」と言い、インターフェースを使う人は「OK、私が書くクラスはそのように見えます」と言います。

インターフェイスは空のシェルですです。メソッドのシグネチャのみがあります。これは、メソッドに本体がないことを意味します。インターフェイスは何もできません。それは単なるパターンです。

例(疑似コード):

// I say all motor vehicles should look like this:
interface MotorVehicle
{
    void run();

    int getFuel();
}

// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{

    int fuel;

    void run()
    {
        print("Wrroooooooom");
    }


    int getFuel()
    {
        return this.fuel;
    }
}

インターフェースの実装は、それがクラスではなく単なる名前の集まりであるので、CPUをほとんど消費しません。したがって、実行するのにコストのかかるルックアップはありません。組み込みデバイスなど、重要な場合に最適です。


抽象クラス

インターフェイスとは異なり、抽象クラスはクラスです。それらを継承するときに実行するルックアップがあるため、使用するのにコストがかかります。

抽象クラスはインターフェースによく似ていますが、それ以外にもいくつかの機能があります。それらの動作を定義できます。「これらのクラスはそのように見えるはずであり、それらは共通しているので、空白を埋めてください!

例えば:

// I say all motor vehicles should look like this:
abstract class MotorVehicle
{

    int fuel;

    // They ALL have fuel, so lets implement this for everybody.
    int getFuel()
    {
         return this.fuel;
    }

    // That can be very different, force them to provide their
    // own implementation.
    abstract void run();
}

// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
    void run()
    {
        print("Wrroooooooom");
    }
}

実装

抽象クラスとインターフェースは異なる概念であることが想定されていますが、実装ではそのステートメントが正しくない場合があります。時には、彼らはあなたが彼らがそう思っているものでさえない。

Javaではこのルールが強く適用されますが、PHPではインターフェイスはメソッドが宣言されていない抽象クラスです。

Pythonでは、抽象クラスはABCモジュールから取得できるプログラミングトリックであり、実際にはメタクラス、つまりクラスを使用しています。そして、インターフェースはこの言語でのダックタイピングとより関連があり、それは、慣習と記述子を呼び出す特別なメソッド(__method__メソッド)の混合です。

プログラミングではいつものように、理論、実践、そして他の言語での実践があります:-)


6
インターフェースに関する重要なポイントは、クラスが何をするかを説明するほど多くはありませんが、Wizzleを使用できるオブジェクトが、Wizzlerを必要とするコードに役立つようにすることができます。多くの場合、ウィズルできるものを書く人も、ウィズラーを必要とする人も、インターフェースを書く人ではないことに注意してください。
スーパーキャット2013年

187
私は、CPU消費がインターフェースのハイライトに値するポイントであるとは思いません。
Dan Lugg、2013

5
@ e-satis CPU使用率のポイントを教えてください。クラスである抽象クラスがCPU使用率を増加させるのはなぜですか?ここでは、どのようなルックアップを参照していますか?
オタク

36
@ e-satis Java 8では、抽象クラスに非抽象メソッドを持つのと同等のインターフェースでデフォルトメソッドを定義できます。この追加により、クラスは複数のインタフェースを実装することができますので、私はもはや私がインターフェイスを使用する必要があるという事実のほかに、抽象クラスとインターフェイス間の実質的な違いを見ることはできませんが、できる唯一の継承1クラス
フィブリノゲン

23
私はとの比較だと思うinterfaceと、classからがHead First Java鮮やかであることA class defines who you are, and an interface tells what roles you could play
LittleLittleQ

872

抽象クラスインターフェースの主な技術的な違いは次のとおりです。

  • 抽象クラスには、定数、メンバー、メソッドスタブ(本体のないメソッド)、および定義済みメソッドを含めることができますが、インターフェイスには定数メソッドスタブしか含めることができません。

  • 抽象クラスのメソッドとメンバーは任意の可視性で定義できますが、インターフェースのすべてのメソッドはpublic(デフォルトではpublicに定義されています)として定義する必要があります。

  • 抽象クラスを継承する場合、具象の子クラスは抽象メソッドを定義する必要がありますが、抽象クラスは別の抽象クラスを拡張でき、親クラスの抽象メソッドを定義する必要はありません。

  • 同様に、別のインターフェースを拡張するインターフェースは、親インターフェースからのメソッドの実装を担当しません。これは、インターフェイスが実装を定義できないためです。

  • 子クラスは単一のクラス(抽象または具象)のみを拡張できますが、インターフェースは拡張でき、クラスは他の複数のインターフェースを実装できます

  • 子クラスは、同じまたはより制限の少ない可視性で抽象メソッドを定義できますが、インターフェースを実装するクラスは、まったく同じ可視性(パブリック)でメソッドを定義する必要があります。


123
これはすべての重要な違いを強調しているので、これが最良の答えだと思います。例は本当に必要ではありません。
ジョシュアK

4
また、通常、クラスを使用すると、CANNOTインスタンス化される抽象クラスとは異なり、オブジェクトをオブジェクトからインスタンス化できます。
SASM 2013

インターフェイスを実装するクラスは、インターフェイスのすべてのメソッドを定義する必要があると思いましたか?
Jiazzyユーザー

@Jiazzyuser抽象クラスがインターフェースを実装する場合、インターフェースのメソッドを実際に定義する必要はありません。その要件は、継承/子具象クラスに委ねることができます。ただし、具象クラスは、親クラスによって実装されていないすべてのインターフェースメソッドを実装する必要があります。この点を説明するために例を追加します。
Justin Johnson

5
「抽象クラスを継承する場合、子クラスは抽象メソッドを定義する必要がありますが、インターフェースは別のインターフェースを拡張でき、メソッドを定義する必要はありません。」- 本当じゃない。インターフェースがメソッドを定義せずにインターフェースを拡張できるように、抽象クラスはメソッドを定義せずに抽象クラスを継承できます。
Nick

141

インターフェースには、機能の定義/シグネチャのみが含まれます。一般的な機能と一般的なシグネチャがある場合は、抽象クラスを使用する必要があります。抽象クラスを使用することで、動作と機能を同時に提供できます。抽象クラスを継承する別の開発者は、空白を埋めるだけでよいため、この機能を簡単に使用できます。

ここに画像の説明を入力してください から取られる:

http://www.dotnetbull.com/2011/11/difference-between-abstract-class-and.html

http://www.dotnetbull.com/2011/11/what-is-abstract-class-in-c-net.html http://www.dotnetbull.com/2011/11/what-is-interface-in -c-net.html


17
これがどの言語に適用されるかを言う必要があります(「抽象クラスは多重継承をサポートしていません」は、普遍的には真実ではありません)
Ben Voigt

最後の比較はテーブルごとに混乱しています!インターフェースのメソッドは静的にすることはできませんが、変数は静的ですfinal抽象クラスに実装されたメソッドは静的にすることができます
realPK

8
インターフェースのメンバーはstatic finalでなければなりません。最後のステートメントは間違っています。
Jawad Zeb 2014

この回答の「機能性」は「実装」を意味すると思います。「動作」が何を意味するのかわからない-多分「署名」?
LarsH

2
ここで対象となるプログラミング言語は何ですか?C#?
Peter Mortensen

80

説明はここにあります:http : //www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm

抽象クラスは、プログラマによって部分的にのみ実装されるクラスです。1つ以上の抽象メソッドが含まれる場合があります。抽象メソッドは、メソッドを子クラスに実装する必要があることをプログラマーに伝えるための関数定義です。

インターフェイスは抽象クラスに似ています。実際、インターフェースはクラスや抽象クラスと同じ名前空間を占めます。そのため、クラスと同じ名前のインターフェイスを定義することはできません。インターフェイスは完全に抽象クラスです。そのメソッドは実装されておらず、そこからサブクラス化するクラスの代わりに、そのインターフェースを実装すると言われています。

とにかく、インターフェースのこの説明はやや混乱します。より一般的な定義は次のとおりです。インターフェイスは、実装クラスが満たす必要があるコントラクトを定義します。インターフェイス定義は、実装コードなしのパブリックメンバーのシグネチャで構成されます。


4
他の言語のインターフェースはクラスが一致しなければならないシグネチャであるのに対し、PHPインターフェースは他の言語とは異なり、PHPインターフェースは内部では抽象クラスであるため、これが最も正しい答えです。ただし、エラーがない限り同じように動作します。
Tor Valamo、

1
確かに、PHPにとってそれは本当の最高のアンサーです。ただし、単純なスニペットよりもテキストBLOBから取得する方が困難です。
e-satis

あなたが提供した定義から、それらは1つの詳細を除いて同じに見えます:インターフェースは100%抽象ですが、抽象クラスは部分的に抽象であり、いくつかのメソッド実装を持つことができます(おそらくすべてのメソッドが実装を持つことができますか?)。
jww 2014

41

多くの回答ですでに述べられている違いを強調したくありません(インターフェイスの変数のパブリック静的最終修飾子および抽象クラスの保護されたプライベートメソッドのサポートに関して)

簡単に言えば、私は言いたい:

インターフェース:複数の無関係なオブジェクトによるコントラクトを実装する

抽象クラス:複数の関連オブジェクト間で同じまたは異なる動作を実装する

Oracleのドキュメントから

次の場合は、抽象クラスの使用を検討してください

  1. 密接に関連するいくつかのクラス間でコードを共有したい。
  2. 抽象クラスを拡張するクラスには、多くの一般的なメソッドやフィールドがあるか、パブリック以外のアクセス修飾子(保護されたものやプライベートなものなど)が必要です。
  3. 非静的フィールドまたは非最終フィールドを宣言したい。

次の場合は、インターフェースの使用を検討してください

  1. 関連のないクラスがインターフェースを実装することを期待しています。たとえば、多くの無関係なオブジェクトがSerializableインターフェイスを実装できます。
  2. 特定のデータ型の動作を指定したいが、その動作を誰が実装するかは気にしない。
  3. タイプの多重継承を利用したい。

抽象クラスは、具象クラスとの「ある」関係を確立します。インターフェイスは、クラスに「ある」機能を提供します。

あなたが探しているなら Javaプログラミング言語としては、さらにいくつかの更新があります。

Java 8は、メソッド機能を提供することにより、interfaceabstractクラスの間のギャップをある程度減らしましたdefaultインターフェースにメソッドの実装がないため、現在は無効になっています。

詳細については、このドキュメントのページ参照してください。

よりよく理解するためのコード例については、このSEの質問をご覧ください。

インターフェイスと抽象クラスの違いをどのように説明すればよいですか?


38

いくつかの重要な違い:

テーブルの形で:

差

以下のようjavapapersからジョーが述べました

1.主な違いは、Javaインターフェースのメソッドは暗黙的に抽象的であり、実装を持つことができないことです。Java抽象クラスには、デフォルトの動作を実装するインスタンスメソッドを含めることができます。

2.Javaインターフェースで宣言された変数は、デフォルトではfinalです。抽象クラスには、非final変数が含まれる場合があります。

3.Javaインターフェースのメンバーはデフォルトでパブリックです。Java抽象クラスは、private、protectedなどのクラスメンバーの通常のフレーバーを持つことができます。

4.Javaインターフェイスは、キーワード「implements」を使用して実装する必要があります。Java抽象クラスは、キーワード「extends」を使用して拡張する必要があります。

5.インターフェースは別のJavaインターフェースのみを拡張でき、抽象クラスは別のJavaクラスを拡張して複数のJavaインターフェースを実装できます。

6.Javaクラスは複数のインターフェースを実装できますが、拡張できる抽象クラスは1つだけです。

7.インターフェイスは完全に抽象的であり、インスタンス化することはできません。Java抽象クラスもインスタンス化できませんが、main()が存在する場合は呼び出すことができます。

8. Java抽象クラスと比較して、Javaインターフェースは追加の間接参照を必要とするため低速です。


3
正しい帰属を提供するために、回答を編集しました。回答の下部にリンクをドロップすることはできません。他のソースからコピーされたすべての言語も引用する必要があります。また、そのテーブルがどこかから作成されたものである場合は、それがどこからのものかを明確に示す必要があります。
ブラッド・ラーソン

C ++についても言及してください。C++にはキーワード「インターフェース」はありませんが、よく尋ねられるQn regd C ++もあります。
cbinder 2014年

@cbinder:c ++にはキーワード「インターフェース」はありません。c ++の違いについては、
1。tutorialspoint.com/cplusplus/cpp_interfaces.htm

@MageshBabu純粋な仮想関数を含むクラスで関数を定義すると、インターフェイスではなく抽象クラスになる可能性があります
cbinder

2
Java 8では、今の違いは少なくなっています。ここで更新の違いを確認してください:journaldev.com/1607/...
パンカジ

31

重要な点は次のとおりです。

  • 抽象はオブジェクト指向です。「オブジェクト」が持つべき基本データおよび/またはそれが実行できるはずの機能を提供します。それは、オブジェクトの基本的な特性、つまり、オブジェクトが何を持ち、何ができるかということに関係しています。したがって、同じ抽象クラスから継承するオブジェクトは、基本的な特性(一般化)を共有します。
  • インターフェイスは機能指向です。オブジェクトが持つべき機能を定義します。それがどのオブジェクトであるかに関係なく、インターフェースで定義されているこれらの機能を実行できる限り、問題ありません。それ以外はすべて無視されます。オブジェクト/クラスには、いくつかの(グループの)機能を含めることができます。したがって、クラスが複数のインターフェースを実装することが可能です。

ありがとうございました。高レベルの対応が得られるところです。もっと理解に基づいた応答を見つけるためにコメントをどれだけ深く掘り下げる必要があるかおかしい。
Andrew

1
他の答えはあまりにも技術的です。これは、私が感じる「正しい」答えに近づいています。OOPの要点はセマンティクスであり、プライベートのネストされたクラスのパブリックゲッターがCPUの負荷の高いルックアップを通じて呼び出されるかどうかは、ここではほとんど関係ありません
Sentinel

26

継承階層でポリモーフィックな動作を提供する場合は、抽象クラスを使用します。

まったく関係のないクラスのポリモーフィックな動作が必要な場合は、インターフェースを使用します。


24

300階建ての建物を建てています

建物の設計図インターフェース

  • たとえば、Servlet(I)

200階まで建てられた建物-部分的に完成--- 要約

  • 部分的な実装(たとえば、汎用サーブレットおよびHTTPサーブレット)

建物の建設が完了- コンクリート

  • 独自のサーブレットなどの完全な実装

インターフェース

  • 実装については何も知りません。要件だけを知っています。インターフェイスに行くことができます。
  • すべてのメソッドはデフォルトでパブリックで抽象的です
  • 100%純粋な抽象クラスです
  • 公に宣言すると、私的で保護された宣言はできません
  • 抽象を宣言すると、final、static、synchronized、strictfp、nativeを宣言できなくなります
  • すべてのインターフェースにパブリック、スタティック、ファイナルがあります
  • インターフェースのインスタンスを作成できないため、シリアル化と一時的は適用できません
  • 最終的なため、不揮発性
  • すべての変数は静的です
  • インターフェース内で変数を宣言するとき、宣言しながら変数を初期化する必要があります
  • インスタンスと静的ブロックは許可されていません

概要

  • 部分的な実装
  • 抽象メソッドがあります。また、コンクリートを使用しています
  • 抽象クラスメソッド修飾子の制限なし
  • 抽象クラス変数修飾子の制限なし
  • アブストラクト以外の他の修飾子を宣言することはできません
  • 変数を初期化する制限はありません

DurgaJobs Webサイトから取得


抽象クラスは、コンストラクタ持つことができます
ビマルクリシュナを

4
私はこの見解に完全に同意しません。ブループリントは、「インターフェース」とはまったく異なるコンセプトです。ブループリントは、特定の実装の静的モデルまたは設計仕様により類似しています。ブループリントはコンストラクターを介して複数回インスタンス化できるため、「クラス」に近いですが、「クラス」には構築方法(ctor)の仕様と実行する手段も含まれているため、これでも十分ではありませんそう。概念としてのインターフェースは、ヒートアップ/クールダウンなど、建物、オーブンなどのさまざまなものに適用できるいくつかの動作を表すことを目的としています
Sentinel

18

この質問にもう一度取り組みましょう。

最初にお知らせするのは、1/1と1 * 1は同じ結果になるということですが、乗算と除算が同じであることを意味するわけではありません。明らかに、彼らはいくつかの良い関係を持っていますが、あなたは両方が異なっていることに注意してください。

主な違いを指摘し、残りはすでに説明されています:

抽象クラスは、クラス階層のモデリングに役立ちます。どのような要件の一見、我々は部分的にどのようにクリアされている正確に構築することですが、私たちは知っているビルドに何を。したがって、抽象クラスは基本クラスです。

インターフェースは、他の階層またはクラスに、私ができることを知らせるのに役立ちます。そして、あなたが私が何かの能力があると言うとき、あなたはその能力を持っている必要があります。インターフェースは、クラスが同じ機能を実装することを強制するものとしてマークします。


2
良い答えですが、数学のメタファーは役に立たないので、このコメントを書くのとほぼ同じ時間だけ読んで無駄にしています。次に、この質問を読んだ他のすべての人と掛け合わせます。
Andrew

「数学の比喩は役に立たない」、なぜそう思うのですか?
ダナンジェイ2017年

12

それは実際にはかなり簡単です。

インターフェースは、抽象メソッドのみを許可され、それ以外は許可されないクラスと考えることができます。

したがって、インターフェイスは「宣言」することだけができ、クラスに持たせたい動作を定義することはできません。

抽象クラスを使用すると、クラスに必要な動作を宣言(抽象メソッドを使用)したり、定義(完全なメソッド実装を使用)したりできます。

また、通常のクラスでは、クラスに必要な動作/アクションを定義するだけで、宣言することはできません。

最後に一つだけ、

Javaでは、複数のインターフェースを実装できますが、拡張できるのは1つ(抽象クラ​​スまたはクラス)だけです...

つまり、定義された動作の継承は、クラスごとに1つしか許可されないように制限されています...つまり、クラスA、B&Cからの動作をカプセル化したクラスが必要な場合は、クラスAがBを拡張し、クラスCがAを拡張する必要があります。それは多重継承をするための少しラウンドアラウンド方法です...

一方、インターフェースは単純に次のようにできます。インターフェースCはA、Bを実装します。

したがって、実質的にJavaは「宣言された動作」、つまりインターフェースでのみ複数の継承をサポートし、定義された動作で単一の継承のみをサポートします。

うまくいけば、それは理にかなっています。


11

インターフェースと抽象クラスの比較が間違っています。代わりに、他に2つの比較があるはずです。1)インターフェイスとクラス、2)抽象クラス最終クラスです。

インターフェイスとクラス

インターフェイスは、2つのオブジェクト間のコントラクトです。たとえば、私は郵便配達員であり、あなたは配達するパッケージです。私はあなたがあなたの配達アドレスを知っていることを期待します。誰かが私にパッケージを与えるとき、それはその配達アドレスを知る必要があります:

interface Package {
  String address();
}

クラスは、契約に従うオブジェクトのグループです。たとえば、私は「ボックス」グループのボックスであり、郵便配達人が必要とする契約に従います。同時に私は他の契約に従います:

class Box implements Package, Property {
  @Override
  String address() {
    return "5th Street, New York, NY";
  }
  @Override
  Human owner() {
    // this method is part of another contract
  }
}

抽象対最終

抽象クラスは、不完全なオブジェクトのグループです。一部欠品しているため使用できません。たとえば、私は抽象的なGPS対応ボックスです-私は地図上で自分の位置を確認する方法を知っています:

abstract class GpsBox implements Package {
  @Override
  public abstract String address();
  protected Coordinates whereAmI() {
    // connect to GPS and return my current position
  }
}

このクラスは、別のクラスによって継承/拡張されている場合、非常に役立ちます。しかし、それ自体-オブジェクトを持つことができないので、それは役に立ちません。抽象クラスは、最終クラスの要素を構築することができます。

最終クラスは、使用できるが変更できない完全なオブジェクトのグループです。彼らは正確にどのように働き、何をすべきかを知っています。たとえば、私は常にその構築中に指定されたアドレスに行くボックスです:

final class DirectBox implements Package {
  private final String to;
  public DirectBox(String addr) {
    this.to = addr;
  }
  @Override
  public String address() {
    return this.to;
  }
}

JavaやC ++のようなほとんどの言語では、クラスだけを持つことが可能です、抽象でも最終でもないます。このようなクラスは継承でき、インスタンス化できます。ただし、これはオブジェクト指向のパラダイムと厳密に一致しているとは思いません。

繰り返しになりますが、抽象クラスとのインターフェースの比較は正しくありません。


9

要約すると、違いは次のとおりです。

インターフェイス抽象クラスの構文の違い:

  1. 抽象クラスのメソッドとメンバーは、任意の可視性を持つことができます。インターフェイスのすべてのメソッドはパブリックである必要があります。// Java 9からもう当てはまりません
  2. 抽象クラスの具象子クラスは、すべての抽象メソッドを定義する必要があります。抽象子クラスは抽象メソッドを持つことができます。インターフェース別拡張は、親インターフェースから継承されたメソッドのデフォルト実装を提供する必要はありません。
  3. 子クラスは、単一のクラスのみを拡張できます。インターフェースは複数を拡張できます。クラスは複数のインターフェースを実装できます。
  4. 子クラスは、可視性が同じか制限が少ない抽象メソッドを定義できますが、インターフェースを実装するクラスは、すべてのインターフェースメソッドをパブリックとして定義する必要があります。
  5. 抽象クラスはコンストラクタを持つことができますが、インターフェースを持つことはできません。
  6. Java 9のインターフェースには、プライベート静的メソッドがあります。

インターフェースで:

public static-サポート
public abstract-サポート
public default-サポート
private static-サポート
private abstract-コンパイルエラー
private default-コンパイルエラー
private-サポート


8

唯一の違いは、1つは多重継承に参加でき、他は参加できないことです。

インターフェースの定義は時間とともに変化しました。インターフェイスはメソッド宣言のみを持ち、単なるコントラクトだと思いますか?静的な最終変数はどうですか?Java 8の後のデフォルト定義はどうですか?

インターフェースはJavaに導入されました。これは多重継承のひし形の問題が原因でありそれが実際に彼らが意図していることです。

インターフェースは、多重継承の問題を回避するために作成された構成要素であり、抽象メソッド、デフォルト定義、および静的な最終変数を持つことができます。

コントラクトを意図しただけの理由で、Javaがインターフェースで静的なfinal変数を許可する理由を参照してください


1
これは重要な違いですが、唯一の違いではありません。
Govind Parmar

7

インターフェース:(左折、右折)

抽象クラス:ホイール。

クラス:ステアリングホイール、ホイールから派生、インターフェイスターンを公開

1つは、さまざまなものにわたって提供できる動作を分類するためのものであり、もう1つは、物のオントロジーをモデル化するためのものです。


6

複数のクラスで使用できる一般的なメソッドがある場合は、抽象クラスを使用してください。そうでなければ、クラスが明確な青写真をたどるようにしたい場合は、インターフェースに行きます。

次の例はこれを示しています。

Javaの抽象クラス:

abstract class animals
{
    // They all love to eat. So let's implement them for everybody
    void eat()
    {
        System.out.println("Eating...");
    }
    // The make different sounds. They will provide their own implementation.
    abstract void sound();
}

class dog extends animals
{
    void sound()
    {
        System.out.println("Woof Woof");
    }
}

class cat extends animals
{
    void sound()
    {
        System.out.println("Meoww");
    }
}

以下は、Javaでのインターフェースの実装です。

interface Shape
{
    void display();
    double area();
}

class Rectangle implements Shape 
{
    int length, width;
    Rectangle(int length, int width)
    {
        this.length = length;
        this.width = width;
    }
    @Override
    public void display() 
    {
        System.out.println("****\n* *\n* *\n****"); 
    }
    @Override
    public double area() 
    {
        return (double)(length*width);
    }
} 

class Circle implements Shape 
{
    double pi = 3.14;
    int radius;
    Circle(int radius)
    {
        this.radius = radius;
    }
    @Override
    public void display() 
    {
        System.out.println("O"); // :P
    }
    @Override
    public double area() 
    { 
        return (double)((pi*radius*radius)/2);
    }
}

一言で言えばいくつかの重要なキーポイント:

  1. Javaインターフェースで宣言された変数は、デフォルトではfinalです。抽象クラスは非最終変数を持つことができます。

  2. Javaインターフェースで宣言された変数は、デフォルトでは静的です。抽象クラスは非静的変数を持つことができます。

  3. Javaインターフェースのメンバーはデフォルトでパブリックです。Java抽象クラスは、private、protectedなどのクラスメンバーの通常のフレーバーを持つことができます。


4

ジュニア開発者の多くは、インターフェース、抽象クラスと具象クラスを同じもののわずかなバリエーションと考えて間違いを犯し、それらの1つを純粋に技術的な理由で選択します。多重継承が必要ですか?一般的な方法を配置するための場所が必要ですか?単なる具体的なクラス以外のものに悩む必要がありますか?これは誤りであり、これらの質問に隠されているのが主な問題です:"I"。自分でコードを書くとき、自分でコードを作成しているとき、コードで作業している、またはコードを使用している他の現在または将来の開発者について考えることはほとんどありません。

インターフェースと抽象クラスは、技術的な観点からは明らかに似ていますが、意味と目的がまったく異なります。

概要

  1. インターフェースは、いくつかの実装があなたのために果たす契約定義します

  2. 抽象クラスは、実装で再利用できるデフォルトの動作提供します

代替要約

  1. インターフェースは公開APIを定義するためのものです
  2. 抽象クラスは内部で使用するためのものであり、SPIを定義するためのものです。

実装の詳細を隠すことの重要性について

具体的なクラスは、非常に特殊な方法で実際の作業を行います。たとえば、ArrayListはメモリの連続した領域を使用して、オブジェクトのリストをコンパクトな方法で格納します。これにより、高速のランダムアクセス、反復、およびインプレース変更が提供されますが、挿入、削除、および場合によっては追加でもひどいです。その間、LinkedListは二重リンクされたノードを使用してオブジェクトのリストを格納します。代わりに、高速の反復、インプレース変更、挿入/削除/追加を提供しますが、ランダムアクセスではひどいです。これら2つのタイプのリストは、さまざまなユースケースに合わせて最適化されており、どのように使用するかが非常に重要です。頻繁にやり取りしているリストからパフォーマンスを絞り出そうとしている場合、およびリストのタイプを選択する場合は、インスタンス化しているリストを慎重に選択する必要があります。

一方、リストの高レベルのユーザーは、リストが実際にどのように実装されるかを実際には気にせず、これらの詳細から隔離する必要があります。JavaがListインターフェースを公開しておらず、List実際にLinkedList現在ある具体的なクラスしか持っていなかったとしましょう。すべてのJava開発者は、実装の詳細に合わせてコードを調整します。ランダムアクセスを回避する、キャッシュを追加してアクセスを高速化する、またはArrayList自分で再実装するだけですが、実際に機能する他のすべてのコードとは互換性がありません。Listのみん。それはひどいでしょう...しかし、Javaマスターが実際に、リンクリストがほとんどの実際のユースケースではひどいことに気付き、その唯一の配列リストに切り替えることにしたと想像してください。Listクラス利用可能。これは世界中のすべてのJavaプログラムのパフォーマンスに影響を与え、人々はそれについて満足しません。そして主な犯人は、実装の詳細が利用可能であったことであり、開発者はそれらの詳細が信頼できる永久的な契約であると想定していました。これが、実装の詳細を隠し、抽象的なコントラクトのみを定義することが重要である理由です。これがインターフェイスの目的です。メソッドが受け入れる入力の種類と期待される出力の種類を定義します。将来の更新で変更される可能性のある内部の詳細に合わせてコードを微調整するようにプログラマを誘惑するようなすべての根拠を公開する必要はありません。 。

抽象クラスは、インターフェースと具象クラスの中間にあります。これは、実装が共通または退屈なコードを共有するのに役立つはずです。たとえば、AbstractCollectionisEmpty、サイズが0に基づいて、contains反復して比較し、addAll繰り返しとしてadd、などの基本的な実装を提供します。これにより、実装はそれらを区別する重要な部分、つまり実際にデータを格納および取得する方法に焦点を合わせることができます。

APIとSPI

インターフェースは、コードのさまざまな部分間の凝集度の低いゲートウェイです。これにより、内部で何かが変更されたときにすべてのライブラリユーザーを壊すことなく、ライブラリが存在し、進化することができます。これは、アプリケーションプログラミングクラスではなく、アプリケーションプログラミングインターフェイスと呼ばれます。小規模では、十分に文書化されたインターフェースを通じてさまざまなモジュールを分離することにより、複数の開発者が大規模プロジェクトでうまく共同作業することもできます。

抽象クラスは、ある程度の実装の詳細を想定して、インターフェースを実装するときに使用される凝集度の高いヘルパーです。または、抽象クラスを使用して、SPI、サービスプロバイダーインターフェイスを定義します。

APIとSPIの違いはわずかですが重要です。APIの場合は、だれそれを使用するかを重視し、SPIの場合はだれそれを実装するかを重視します。

APIへのメソッドの追加は簡単で、APIの既存のユーザーはすべてコンパイルされます。すべてのサービスプロバイダー(具体的な実装)が新しいメソッドを実装する必要があるため、SPIへのメソッドの追加は困難です。インターフェイスを使用してSPIを定義する場合、プロバイダーはSPIコントラクトが変更されるたびに新しいバージョンをリリースする必要があります。代わりに抽象クラスを使用する場合、新しいメソッドは既存の抽象メソッドで定義することも、空のthrow not implemented exceptionスタブとして定義することもできます。これにより、古いバージョンのサービス実装を引き続きコンパイルして実行できます。

Java 8とデフォルトのメソッドに関する注意

Java 8はインターフェースのデフォルトメソッドを導入しましたが、これによりインターフェースと抽象クラス間の境界がさらにぼやけますが、これは実装がコードを再利用できるようにするためではなく、APIとSPIの両方として機能するインターフェースを簡単に変更できるようにするためです(または抽象クラスの代わりにSPIを定義するために誤って使用されています)。

どちらを使用しますか?

  1. される事はすることになって公に使用コードの他の部分、または他の外部コードで?インターフェースを追加して、実装の詳細をパブリック抽象コントラクトから隠します。これは、Thingの一般的な動作です。
  2. ある事の共通のコードの多くの複数の実装を持っているはずの何かが?インターフェイスと抽象的な不完全な実装の両方を作成します。
  3. 実装は1つしかなく、他の誰もそれを使用しませんか?それを具体的なクラスにしてください。
    1. 「いつまでも」は長い時間です。安全にプレイし、その上にインターフェースを追加することができます。

当然の結果:他の方法で回避がしばしば誤って行われます。使用しているときのことを、いつもあなたが実際に必要とすることが最も一般的なクラス/インタフェースを使用するようにしてください。言い換えるとArrayList theList = new ArrayList()配列リストであることに非常に強い依存関係がない限り、変数をとして宣言しないでください。他のタイプのリストがそれをカットすることはありません。List theList = new ArrayList代わりに、またはCollection theCollection = new ArrayListそれがリストであり、他のタイプのコレクションが実際には問題ではない場合でも使用してください。


4

実際には元の質問に対する答えではありませんが、それらの違いに対する答えが得られたら、いつ使用するかというジレンマを入力 します。インターフェイスまたは抽象クラスをいつ使用するか?どちらを使用するのですか?

OOPについての知識は限られていますが、インターフェイスを文法の形容詞に相当するものと見なすことで、今まではうまくいきました(この方法が間違っている場合は修正してください!)。たとえば、インターフェイス名は、クラスに与えることができる属性または機能のようなものであり、クラスにはそれらの多くを持つことができます:ISerializable、ICountable、IList、ICacheable、IHappy、...


3

継承は次の2つの目的で使用されます。

  • オブジェクトが親型のデータメンバーとメソッドの実装を独自のものと見なせるようにします。

  • 1つのタイプのオブジェクトへの参照を、スーパータイプオブジェクトへの参照を期待するコードで使用できるようにします。

一般化された多重継承をサポートする言語/フレームワークでは、タイプを「インターフェース」または「抽象クラス」として分類する必要はほとんどありません。ただし、一般的な言語とフレームワークでは、他の任意の数の型の代わりに型を使用できるとしても、他の型のデータメンバーまたはメソッド実装を独自のものと見なすことができます。

抽象クラスにはデータメンバーとメソッド実装がありますが、他のクラスから継承しないクラスによってのみ継承できます。インターフェイスは、それらを実装する型にほとんど制限を課しませんが、データメンバーやメソッド実装を含めることはできません。

型が多くの異なるものの代わりに使用できると便利な場合があります。オブジェクトが親型のデータメンバーとメソッドの実装を独自のものと見なすと便利な場合もあります。インターフェースと抽象クラスを区別することで、これらの機能のそれぞれを、最も関連性の高い場合に使用できます。


3

キーポイント:

  • 抽象クラスは、プロパティ、データフィールド、メソッド(完全/不完全)の両方を持つことができます。
  • メソッドまたはプロパティが、派生クラスでオーバーライドする必要がある抽象キーワードで定義されている場合(密結合機能として機能します)
  • メソッドまたはプロパティの抽象キーワードを抽象クラスで定義する場合、メソッドの本体とプロパティの取得/設定値を定義できず、派生クラスでオーバーライドする必要があります。
  • 抽象クラスは多重継承をサポートしていません。
  • 抽象クラスにはコンストラクタが含まれます。
  • 抽象クラスには、サブルーチン、関数、プロパティのアクセス修飾子を含めることができます。
  • 抽象クラスの完全なメンバーのみを静的にすることができます。
  • インターフェイスは別のインターフェイスからのみ継承でき、抽象クラスからは継承できません。抽象クラスは別の抽象クラスまたは別のインターフェイスから継承できます。

利点:

  • これは、すべてのサブクラスが同じ階層または標準を実行することを強制する一種の契約です。
  • さまざまな実装が同じ種類であり、共通の動作またはステータスを使用する場合は、抽象クラスを使用することをお勧めします。
  • 抽象クラスに新しいメソッドを追加する場合、デフォルトの実装を提供するオプションがあるため、既存のすべてのコードが適切に機能する可能性があります。
  • インターフェースよりも高速に実行できます(インターフェースは、対応するクラスで実際のメソッドを見つけるのにより多くの時間が必要です。)
  • 密結合および疎結合に使用できます。

詳細はこちら... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/


3

要約すると、次のようになりinterfaceます。

  1. 離れてから、完全に抽象defaultおよびstatic方法; defaultstaticメソッドの定義(メソッドシグネチャ+実装)がありますが、他のメソッドの宣言(メソッドシグネチャ)しかありません。
  2. クラスよりも緩いルールに従います(クラスは複数interfaceのを実装interfaceでき、は複数interfaceのから継承できます)。指定されているかどうかにかかわらpublic static finalず、すべての変数は暗黙的に定数です。publicそのように指定されているかどうかにかかわらず、すべてのメンバーは暗黙的にです。
  3. 一般に、実装クラスが指定された機能を持っているか、同じインターフェイスを実装する他のクラスと互換性があるかを保証するために使用されます。

一方、abstractクラスは次のとおりです。

  1. 完全に抽象化されたものから完全に実装されたものまで、1つ以上のabstractメソッドを持つ傾向があります。宣言と定義の両方を含めることができ、宣言は次のようにマークされますabstractます。
  2. 完全なクラスであり、インスタンス化できないという条件で、他のクラスを管理するルールに従います(1つのクラスからのみ継承できます)(完全に実装されている保証がないため)。非定数のメンバー変数を持つことができます。、メンバーのアクセス制御を実装してメンバーを制限することができprotectedprivateまたはプライベートパッケージ(詳細不明)。
  3. 一般に、複数のサブクラスで共有できる限りの実装を提供するため、またはプログラマーが提供できる限りの実装を提供するために使用されます。

または、すべてを1つの文に要約したい場合:An interfaceは実装クラスが持ってabstractいるものですが、クラスはサブクラス何であるかです


3

意味のあるもう1つの違いを追加したいと思います。たとえば、何千行ものコードを含むフレームワークがあるとします。次に、enhanceUI()メソッドを使用してコード全体に新しい機能を追加する場合、そのメソッドをインターフェイスではなく抽象クラスに追加することをお勧めします。このメソッドをインターフェイスに追加する場合は、実装されているすべてのクラスに実装する必要がありますが、メソッドを抽象クラスに追加する場合はそうではありません。


3

シンプルだが明確な答えを与えるには、コンテキストを設定することが役立ちます。完全な実装を提供したくない場合は、両方を使用します。

主な違いは、インターフェイスには実装がまったくないこと(ボディなしのメソッドのみ)ですが、抽象クラスにはメンバー付きのメソッドとボディを持つメソッド、つまり部分的に実装することもできます。


あなたがたった今答えたので、あなたの答えはdefaultあなたがインターフェースで具体的なメソッドを同様に定義することができるJava 8 のキーワードを考慮に入れていません。
philantrovert 2017年

私が言ったように、これは違いが何であるかを学ぶ段階にいる誰かにとって「単純だが明確な答え」であることを意味していました。そのような人にとって、そのような例外について知ることは何の利点もありません、それは非常に混乱するだけです。
user3775501

3

実際の実装に代わる抽象クラスとインターフェースの違い。

インターフェース:これはキーワードであり、オブジェクトのテンプレートまたはブループリントを定義するために使用され、すべてのサブクラスが同じプロトタイプに従うことを強制します。実装に関しては、すべてのサブクラスは自由に機能を実装できますそれは要件です。

インターフェースを使用する必要がある他のユースケースのいくつか。

インターフェイスを介して行われる2つの外部オブジェクト間の通信(アプリケーションへのサードパーティ統合)ここでのインターフェイスは、契約として動作します。

抽象クラス:抽象、それはキーワードであり、クラスの前にこのキーワードを使用すると、抽象クラスになります。主に、テンプレートと、すべてのオブジェクトが従うオブジェクトのデフォルト機能を定義する必要がある場合に使用されます。サブクラスを使用すると、冗長コードが削除され、他のクラスがクラスのオブジェクトを直接インスタンス化できないようにするなど、抽象クラスを使用できるもう1つの使用例が得られます。機能を使用できるのは派生クラスのみです。

抽象クラスの例:

 public abstract class DesireCar
  {

 //It is an abstract method that defines the prototype.
     public abstract void Color();

  // It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.   
 // and hence no need to define this in all the sub classes in this way it saves the code duplicasy     

  public void Wheel() {          

               Console.WriteLine("Car has four wheel");
                }
           }


    **Here is the sub classes:**

     public class DesireCar1 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red color Desire car");
            }
        }

        public class DesireCar2 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red white Desire car");
            }
        }

インターフェースの例:

  public interface IShape
        {
          // Defines the prototype(template) 
            void Draw();
        }


  // All the sub classes follow the same template but implementation can be different.

    public class Circle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Circle");
        }
    }

    public class Rectangle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Rectangle");
        }
    }

3

インターフェース抽象クラスの明確な違いを見つけることができます

インターフェース

  • インターフェイスには抽象メソッドのみが含まれます。
  • インターフェイスを実装するときに、ユーザーにすべてのメソッドの実装を強制します。
  • finalおよびstatic変数のみが含まれます。
  • interfaceキーワードを使用して宣言します。
  • インターフェイスのすべてのメソッドはパブリックとして定義する必要があります。
  • インターフェースを拡張することも、クラスが他の複数のインターフェースを実装することもできます。

抽象クラス

  • 抽象クラスには、抽象メソッドと非抽象メソッドが含まれています。

  • 抽象クラスを継承した場合、ユーザーにすべてのメソッドの実装を強制しません。

  • プリミティブと非プリミティブを含むすべての種類の変数が含まれています

  • 抽象キーワードを使用して宣言します。

  • 抽象クラスのメソッドとメンバーは、任意の可視性で定義できます。

  • 子クラスは、単一のクラス(抽象または具象)のみを拡張できます。


2

抽象クラスは、オブジェクトを作成できないクラス、またはインスタンス化できないクラスです。抽象メソッドはクラスを抽象化します。抽象クラスで宣言されているメソッドをオーバーライドするには、抽象クラスを継承する必要があります。アクセス指定子に制限はありません。抽象クラスには、コンストラクターとその他の具象(非abstarctメソッド)メソッドを含めることができますが、インターフェースには含めることができません。

インターフェースはメソッドの青写真/テンプレートです(たとえば、紙の家が与えられます(インターフェースハウス)。さまざまな建築家がアイデアを使用してそれを構築します(家のインターフェースを実装する建築家のクラス)。これは、抽象メソッド、デフォルトメソッド、静的メソッド、最終変数、およびネストされたクラス。すべてのメンバーはfinalまたはpublicであり、保護されたプライベートのアクセス指定子は許可されていません。オブジェクトの作成は許可されていません。使用するためにクラスを作成する必要がありますインターフェースを実装し、インターフェースで宣言された抽象メソッドをオーバーライドします。インターフェースは、疎結合の良い例です(動的ポリモーフィズム/動的バインディング)インターフェースは、ポリモーフィズムと抽象化を実装します。実装クラス。たとえば、自動車会社であり、製造しているすべての車で一部の機能が同じになるようにしたいので、会社はそれらの機能を備えたインターフェース車両を作成し、異なるクラスの車(Maruti Suzkhi、Maruti 800など)をオーバーライドします。それらの機能(機能)。

抽象クラスがすでにあるのに、なぜインターフェースするのですか?Javaはマルチレベルの階層継承のみをサポートしますが、インターフェースの助けを借りて、多重継承を実装できます。


2

実用性の観点から(JAVA)、抽象クラスとインターフェイスの主な違いは、 抽象クラスが状態を保持できることです。 状態を保持する以外に、インターフェイスを使用して残りの操作を行うこともできます。


1

インターフェースでは、すべてのメソッドは定義のみである必要があり、単一のメソッドは実装しないでください。

しかし、抽象クラスでは、定義のみを持つ抽象メソッドが必要ですが、他のメソッドも実装を持つ抽象クラスに含めることができます...


1

インターフェースと抽象クラスの間には、さまざまな構造的/構文的な違いがあります。さらにいくつかの違いは

[1] シナリオベースの違い

抽象クラスは、ユーザーが親クラスのオブジェクトを作成することを制限するシナリオで使用され、さらに抽象メソッドが将来追加されると考えています。

提供する必要のある抽象メソッドが残っていないことが確実な場合は、インターフェースを使用する必要があります。その後、インターフェイスのみが公開されます。

[2] 概念の違い

「将来的には、より多くの抽象メソッドを提供する必要がありますか」YESの場合は抽象クラスにし、NOの場合はインターフェイスにします。

(Java 1.7まで最も適切で有効)


1

通常、何かのコアに使用される抽象クラスですが、ペリフェラルの追加に使用されるインターフェースです。

車両の基本タイプを作成する場合は抽象クラスを使用する必要がありますが、車両の基本概念の一部ではない機能やプロパティを追加する場合は、インターフェースを使用する必要があります。たとえば、「ToJSON()」関数を追加します。

インターフェイスは、抽象クラスではなく幅広い抽象化を備えています。これは、arguments.passingの例で確認できます。

ここに画像の説明を入力してください

引数として車両を使用する場合は、その派生型の1つ(バスまたは車と同じカテゴリ、車両カテゴリのみ)を使用できます。ただし、引数としてIMoveableインターフェイスを使用する場合は、より多くの選択肢があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.