web-dev-qa-db-ja.com

インタフェースと抽象クラス(一般的なオブジェクト指向)

私は最近、インタフェイスクラスと抽象クラスの違いについて質問された2回の電話インタビューを受けました。私は私が考えることができるそれらのすべての側面を説明しました、しかし、彼らは私が特定の何かを述べるのを待っているようです、そしてそれが何であるかわかりません。

私の経験から、私は次のことが正しいと思います。重要な点を見逃している場合はお知らせください。

インターフェース:

インタフェースで宣言されたすべての単一のメソッドは、サブクラスで実装される必要があります。イベント、デリゲート、プロパティ(C#)、およびメソッドのみがインタフェースに存在できます。クラスは複数のインタフェースを実装できます。

抽象クラス:

サブクラスで実装する必要があるのは抽象メソッドだけです。抽象クラスは、実装を持つ通常のメソッドを持つことができます。抽象クラスは、イベント、デリゲート、プロパティ、メソッド以外にクラス変数を持つこともできます。 C#に多重継承が存在しないために、クラスが実装できる抽象クラスは1つだけです。

  1. 結局のところ、インタビュアーは質問「あなたが抽象メソッドだけを持つ抽象クラスを持っていたらどうしますか?それはインターフェースとどう違うのでしょうか」という質問を思いつきました。私は答えを知りませんでしたが、私はそれが上で述べたように継承だと思いますか?

  2. 別のインタビュアーから、インターフェース内にパブリック変数があるとしたら、抽象クラスとはどう違うのですか。私はあなたがインターフェイスの中にパブリック変数を持つことはできないと主張しました。私は彼が何を聞きたがっているのかわかりませんでしたが、彼も満足しませんでした。

関連項目 : 

1286
Houman

あなたの質問はそれが "一般的なオブジェクト指向"のためのものであることを示していますが、それは実際にこれらの用語の.Net使用に焦点を当てているようです。

.NET(Javaの場合と同様)

  • インタフェースは状態や実装を持つことができません
  • インタフェースを実装するクラスは、そのインタフェースのすべてのメソッドの実装を提供しなければなりません
  • 抽象クラスは状態(データメンバ)や実装(メソッド)を含むことができます。
  • 抽象クラスは抽象メソッドを実装せずに継承することができます(ただし、そのような派生クラスはそれ自体抽象です)。
  • インタフェースは多重継承、抽象クラスではないかもしれません(これがインタフェースが抽象クラスとは別に存在する主な具体的な理由です - 一般的なMIの問題の多くを取り除く多重継承の実装を可能にします).

一般的なOOの用語として、違いは必ずしも明確に定義されていません。たとえば、似たような厳密な定義(インターフェースは実装を含むことができない抽象クラスの厳密なサブセットです)を保持するC++プログラマがいますが、デフォルト実装を持つ抽象クラスは依然としてインターフェースであるとか非抽象クラスはインタフェースを定義できます。

確かに、パブリックメソッドがプライベート仮想メソッドに対して「サンク」している非仮想メソッドである、Non-Virtual Interface(NVI)と呼ばれるC++イディオムがあります。 

676
Michael Burr

アナロジーはどうでしょうか。私が空軍にいたとき、私はパイロット訓練を受け、そしてアメリカ空軍のパイロットになりました。その時点で私は何も飛行する資格がなく、航空機タイプの訓練に参加しなければなりませんでした。資格を取得すると、私はパイロット(抽象クラ​​ス)とC-141パイロット(具象クラス)になりました。私の任務の1つで、私は追加の義務を与えられました:安全責任者。今はまだパイロットでC-141のパイロットでしたが、安全管理者の職務も担当しました(いわばISafetyOfficerを実装しました)。パイロットは安全管理者である必要はありませんでした、他の人々も同様にそれをしたかもしれません。

すべてのUSAFパイロットは特定の空軍全体の規則に従わなければなりません、そしてすべてのC-141(またはF-16、またはT-38)パイロットは '' USAFパイロットです。誰でも安全担当者になれます。要約すると:

  • パイロット:抽象クラス
  • C-141パイロット:具象クラス
  • ISafety Officer:インターフェース

付記:これは概念を説明するのを助けるための類推であり、コーディングの推奨事項ではありません。下記の様々なコメントを見てください、議論はおもしろいです。

796
Jay

彼らが探している答えは、基本的またはOPPSの哲学的な違いだと思います。

抽象クラスの継承は、派生クラスが抽象クラスのコアプロパティと動作を共有するときに使用されます。実際にクラスを定義する種類の動作。

一方、インターフェース継承は、クラスが周辺の振る舞いを共有する場合に使用されます。これは必ずしも派生クラスを定義するわけではありません。

例えば。 CarとTruckは、Automobile抽象クラスのコアプロパティと動作の多くを共有していますが、DrillersやPowerGeneratorsのような非自動車クラスでさえ共有し、必ずしもCarやTruckを定義していないしたがって、Car、Truck、Driller、PowerGeneratorはすべて同じIExhaustインターフェイスを共有できます。

207
Prasun

短い:抽象クラスは モデリング 類似したクラスのクラス階層に使用されます(例えば、Animalは抽象クラス、Human、Lion、Tigerは具象派生クラスになります)。

そして 

インターフェースは 通信 インターフェースを実装するクラスのタイプを気にしない2つの類似/非類似クラス間で使用されます(例:Heightはインターフェースプロパティで、Human、Building、Treeによって実装できます)。あなたが食べることができるならば、あなたはあなたが死ぬことができるか何かを泳ぐことができます..それはあなたがHeight(あなたのクラスの実装)を持っている必要があることだけ問題です。 

180
Dhananjay

他にもいくつか違いがあります -

インターフェースは具体的な実装を持つことはできません。抽象基本クラスはできます。これにより、具体的な実装をそこに提供できます。これにより、抽象基本クラスが実際にはより厳密なコントラクトを提供できるようになります。ただし、インタフェースは実際にはクラスの使用方法のみを記述します。 (抽象基本クラスは、振る舞いを定義する非仮想メンバーを持つことができ、それによって基本クラスの作者により多くの制御が与えられます。)

クラスには複数のインタフェースを実装できます。クラスは、単一の抽象基本クラスからしか派生できません。これにより、インタフェースを使用した多相階層が可能になりますが、抽象基底クラスはできません。これにより、インタフェースを使用した擬似多重継承も可能になります。

抽象基本クラスは、APIを壊すことなくv2 +で変更できます。インターフェースへの変更は重大な変更です。

[C#/。NET固有]抽象基本クラスとは異なり、インタフェースは値型(構造体)に適用できます。構造体は抽象基本クラスから継承できません。これにより、行動契約/使用ガイドラインを値タイプに適用できます。

76
Reed Copsey

継承
車とバスを考えます。彼らは2つの異なる乗り物です。それでも、彼らはステアリング、ブレーキ、ギア、エンジンなどを持っているように彼らはいくつかの共通のプロパティを共有しています.
継承の概念では、これは次のように表すことができます。

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In Java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

今自転車… 

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

そして車….

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

それがInheritanceについてのすべてです。上で見たように、それらを使ってオブジェクトをより単純なBaseフォームとその子に分類します。

抽象クラス

抽象クラスは不完全オブジェクトです。さらに理解するために、もう一度車両のアナロジーを考えてみましょう。
車を運転することができます。右?しかし、異なる車両は異なる方法で運転されます。たとえば、自転車を運転するのと同じように車を運転することはできません。
それでは、どのようにして車両の運転機能を表現するのでしょうか。どのような種類の車であるかを確認し、独自の機能で運転することは困難です。新しいタイプの車両を追加するときは、Driverクラスを何度も変更する必要があります。
これが抽象クラスと抽象メソッドの役割です。継承するすべての子がこの関数を実装する必要があることを伝えるために、driveメソッドをabstractとして定義できます。
それであなたが車のクラスを変更したら….

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

自転車と車もそれを運転する方法を指定する必要があります。そうでなければ、コードはコンパイルされず、エラーがスローされます。
つまり、抽象クラスは、不完全な関数を持つ部分的に不完全なクラスであり、継承している子はそれ自身を指定しなければなりません。

インターフェース インターフェースは完全に不完全です。それらには特性がありません。彼らはただ継承している子供たちが何かをすることができるということを示します...
あなたがあなたと携帯電話の種類が異なるとします。それぞれに異なる機能を実行する方法があります。例:人を呼ぶ。電話のメーカーはそれをする方法を指定します。ここで携帯電話は番号をダイヤルできます - つまり、ダイヤル可能です。これをインターフェースとして表現しましょう。

public interface Dialable {
    public void dial(Number n);
}

ここでDialableのメーカーは、番号をダイヤルする方法を定義します。あなたはそれにダイヤルする番号を与える必要があります。 

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

これにより、抽象クラスの代わりにインタフェースを使用することで、Dialableを使用する関数の作成者はそのプロパティについて心配する必要がなくなります。例:それはタッチスクリーンまたはダイヤルパッドを持っていますか、それは固定の固定電話または携帯電話ですか?あなたはそれがダイヤル可能かどうかを知る必要があります。 Dialableインタフェースを継承(または実装)しますか。 

そしてもっと重要なことに、いつかあなたが別のものとDialableを切り替えるなら

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Dialableを使用する関数はDialableインタフェースで指定されたもの以外の詳細に依存しない(できない)ため、コードはまだ完全に機能することを確認できます。どちらもDialableインターフェースを実装しており、それがこの関数が気にする唯一のものです。

インターフェイスは、共通の機能を共有する限り(オブジェクトを固定電話や携帯電話に変更するのと同じように、番号をダイヤルする必要がある限り)、オブジェクト間の相互運用性を保証するために開発者が共通して使用します。つまり、インタフェースは、プロパティを持たない、より単純な抽象クラスの抽象クラスです。
また、必要なだけ多くのインターフェースを実装(継承)できますが、単一の親クラスのみを拡張(継承)できます。 

詳細情報 抽象クラスとインタフェース

66
fz_salam

この質問に答えるためにJavaをOOP languageと見なした場合、Java 8リリースでは上記の回答の内容の一部が廃止されています。現在のJavaインタフェースは、具象実装によるデフォルトのメソッドを持つことができます。 

Oracle websiteinterfaceクラスとabstractクラスの主な違いを説明しています。

抽象クラスの使用を検討してください if:

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

インターフェースの使用を検討してください if:

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

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

interface:複数の無関係なオブジェクトによるコントラクトを実装するため

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

明確な方法で物事を理解するためにコード例を見てください: どのように私はインターフェースと抽象クラスの間の違いを説明するべきですか?

37
Ravindra babu

インタビュアーは奇妙な木を吠えています。 C#やJavaなどの言語には違いがありますが、C++などの他の言語には違いがあります。 OO理論はこの2つを区別するものではなく、単に言語の構文です。

抽象クラスは、継承される実装とインタフェース(純粋仮想メソッド)の両方を持つクラスです。インタフェースは一般的に実装を持たず、純粋仮想関数のみを持ちます。

C#やJavaでは、実装されていない抽象クラスは、それを継承するために使用される構文と、1つからしか継承できないという点でインタフェースと異なります。

32
Steve Rowe

インターフェースを実装することで、継承( "is-a"関係)ではなく合成( "has-a"関係)を達成しています。継承ではなく動作の構成を実現するためにインターフェイスを使用する必要があるデザインパターンのようなことに関しては、覚えておくべき重要な原則です。

31
TheTXI

インターフェイスと抽象クラスの概要を知っている場合は、インターフェイスを使用する必要があるときと抽象クラスを使用するときの最初の質問が頭に浮かんできます。インタフェースと抽象クラスの説明.

  1. いつInterfaceを使うべきですか?

    もしあなたが実装について知らないのであれば、我々は要求仕様を持っているだけで、それから我々はインタフェースに行きます  

  2. 抽象クラスを使うべき時は?

    実装を知っていても完全に(部分的には実装されていない)場合は、抽象クラスを使います。  

    インターフェース

    デフォルトのpublic abstractによるすべてのメソッドは、インタフェースが100%純粋なabstractであることを意味します。

    要約

    具象メソッドと抽象メソッドを持つことができます。具体的メソッドとは抽象クラスで実装されたものです。抽象クラスは抽象として宣言されるクラスです。抽象メソッドは抽象メソッドを含んでも含まなくてもかまいません。

    インターフェース

    保護されたプライベートとして保護することはできません。

    Q. Interfaceを非公開で保護されていると宣言していないのはなぜですか。

    デフォルトではインターフェースメソッドはpublic abstractであるため、そのため、インターフェースをprivateおよびprotectedとして宣言していません。

    インターフェース方法
    また、インターフェイスを非公開、保護、最終、静的、同期、ネイティブと宣言することはできません.....

    理由を挙げます。なぜインターフェイスのオブジェクトを作成し同期することができないために同期化メソッドを宣言していないのかオブジェクト上での作業が同期化メソッドを宣言していない理由また、同期は一時的に機能するため、適用されません。

    要約  

    私達は公共の、私用の最終的な静的なものと楽しく使用しています....抽象的に制限が適用できないことを意味します。

    インターフェース

    変数は、デフォルトではpublic static finalとして宣言されているので、private、protectedとしても宣言されていません。

    インターフェイス変数はデフォルトではpublic static finalおよびfinal変数なので、変数に値を代入し、変数をインターフェイスに宣言した後は値を変更する必要があるため、volatile修飾子はインターフェイスには適用できません。

    そして揮発性変数は変化し続けるので反対です。最後に、それがインターフェースでvolatile変数を使用していない理由です。

    要約

    抽象変数はpublic static finalを宣言する必要はありません。

この記事が役に立つことを願っています。

25
JegsVala

概念的には、言語固有の実装、規則、利点を維持し、いずれかまたは両方を使用してプログラミング目標を達成する

1 - 抽象(または純粋な抽象)クラスは階層を実装するためのものです。ビジネスオブジェクトが構造的に類似しているように見え、親子関係(階層構造)の関係だけを表す場合は、継承/抽象クラスが使用されます。ビジネスモデルに階層がない場合は、継承を使用しないでください(ここでは、プログラミングロジックについては説明しません。たとえば、一部のデザインパターンでは継承が必要です)。概念的には、抽象クラスはOOPでビジネスモデルの階層を実装するためのメソッドです。インターフェースとは無関係です。実際には抽象クラスとインターフェースを比較しても意味がありません。実装が問題になる場合、概念はどちらもやや同じ機能を提供するように見えるため、プログラマは通常コーディングを重視します。 [抽象は抽象クラスとは異なることにも注意してください]。

2 - インターフェイスは契約、1つまたは複数の機能のセットによって表される完全なビジネス機能です。それが実装され継承されていない理由です。ビジネスオブジェクト(階層の一部であるかどうかに関係なく)は、完全なビジネス機能をいくつでも持つことができます。抽象クラスとは関係がないのは、一般的な継承を意味します。例えば、人間は走ることができ、象は走ることができ、鳥は走ることができ、そして以下同様に、異なる階層のこれらすべてのオブジェクトは、RUNインターフェースまたはEATまたはSPEAKインターフェースを実装するであろう。これらのインタフェースを実装する各型の抽象クラスを持つものとして実装する可能性があるため、実装に参加しないでください。任意の階層のオブジェクトは、その階層とは関係のない機能(インターフェース)を持つことができます。 

私は、インターフェースは多重継承を実現したり、公の振る舞いを公開したりするために発明されたものではなく、同様に純粋な抽象クラスはインターフェースを覆すものではない親のコア構造(プロパティ+機能性)を持つ子を生成するための階層の親

違いについて尋ねられた場合、それは実際には概念的な違いであり、明示的に求められない限り、言語固有の実装における違いではありません。 

私は両方のインタビュアーがこれら2つの間に1行の直接的な違いを期待していて、あなたが失敗したとき彼らは他のものとして一つを実装することによってこの違いに向かってあなたを動かそうとした

抽象メソッドのみを持つ抽象クラスがあったとしたらどうでしょうか。

24
bjan

.Netの場合 

2番目のインタビュアーに対するあなたの答えは、最初の1人に対する答えでもあります。 

編集:別のメモで、私は「サブクラス」(または「継承」という句)というフレーズを、インターフェースを「実装する」ように定義されているクラスを記述するために使うことすらないでしょう。私にとって、インターフェースとは、そのインターフェースを「実装」するように定義されている場合にクラスが準拠しなければならない規約の定義です。それは何も継承しません...あなたはすべて明示的に自分自身で追加しなければなりません。 

21
Charles Bretana

あなたが設計のものではなく技術的な違いを与えたので、彼らはあなたの反応を好きではなかったと思います。質問は私にとってトロールの質問のようなものです。実際、インターフェースと抽象クラスはまったく異なる性質を持っているため、実際にそれらを比較することはできません。私はあなたに、インターフェースの役割と抽象クラスの役割とは何かについての私のビジョンをお伝えします。

interface: は、より保守しやすく、スケーラブルでテストしやすいアプリケーションを持つために、契約を確実にし、クラス間の結合を少なくするために使用されます。

抽象クラス: は、同じ責任のクラス間でコードを因数分解するためにのみ使用されます。これがOOPで多重継承が悪いことである主な理由であることに注意してください。なぜなら クラスは多くの責任を扱うべきではないからです (代わりに composition を使ってください)。

したがって、インターフェースは実際のアーキテクチャ上の役割を果たしますが、抽象クラスはほとんど実装の詳細に過ぎません(もちろんそれを正しく使用する場合)。

17
Gnucki

Interface :互いに関連している場合もそうでない場合もあるコンポーネントに関する規則を暗示したい場合は、を使用する必要があります。

長所:

  1. 多重継承を許可する
  2. どのような種類のオブジェクトがコンテキスト内で使用されているのかを公開しないことによって抽象化を提供します。
  3. 契約の特定の署名による一貫性を提供します。

短所:

  1. 定義されたすべての契約を履行しなければならない
  2. 変数やデリゲートは持てません
  3. 一度定義すると、すべてのクラスを壊さずに変更することはできません。

抽象クラス :互いに関連するコンポーネントの基本的またはデフォルトの動作または実装が必要な場合に使用します。

長所:

  1. インターフェースより速い
  2. 実装に柔軟性があります(完全にまたは部分的に実装できます)。
  3. 派生クラスを壊すことなく簡単に変更できます

短所:

  1. インスタンス化できません
  2. 多重継承をサポートしていません
14
After all that, the interviewer came up with the question "What if you had an 
Abstract class with only abstract methods? How would that be different
from an interface?" 

ドキュメント 抽象クラスが抽象メソッド宣言のみを含む場合は、代わりにそれをインタフェースとして宣言するべきであると明確に言う。

An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?

インタフェースの変数は、デフォルトではpublic staticおよびfinalです。抽象クラスのすべての変数がパブリックである場合、質問はどうなるでしょうか。それでも、インターフェースの変数とは異なり、静的ではなく、最終的でなくてもかまいません。

最後に、上記のものにもう1点追加します。抽象クラスは依然としてクラスであり、単一の継承ツリーに分類されますが、インターフェイスは複数の継承に存在できます。

13
Aniket Thakur
  1. インタフェース:
    • メソッドを実装(または定義)するのではなく、派生クラスで行います。
    • インターフェイスでメンバ変数を宣言しません。
    • インタフェースはHAS-A関係を表します。つまり、それらはオブジェクトのマスクです。
  2. 抽象クラス:
    • 抽象クラスでメソッドを宣言し定義することができます。
    • そのコンストラクタを隠します。つまり、そこから直接作成されたオブジェクトはありません。
    • 抽象クラスはメンバ変数を保持できます。
    • 派生クラスは抽象クラスを継承します。つまり、派生クラスのオブジェクトはマスクされず、抽象クラスを継承します。この場合の関係はIS-Aです。

これは私の意見です。

12
nautilusvn

Jeffrey RichterによるC#を介したCLRからのコピー...

私はよく「基本型とインターフェースのどちらを設計すべきか」という質問をよく聞きますが、その答えは必ずしも明確ではありません。

ここにあなたを助けるかもしれないいくつかのガイドラインがあります:

■IS-AとCAN-DOの関係型は1つの実装しか継承できません。派生型が基本型とのIS-A関係を主張できない場合は、基本型を使用しないでください。インターフェースを使用する。インターフェースはCAN-DO関係を意味する。 CAN-DO機能がさまざまなオブジェクトタイプに属していると思われる場合は、インターフェイスを使用してください。例えば、型はそれ自身のインスタンスを別の型(IConvertible)に変換することができます、型はそれ自身のインスタンスを直列化することができます(ISerializable)、など。値型はSystem.ValueTypeから派生する必要があるため、任意の基本クラスから派生することはできません。この場合、CAN-DO関係を使用してインタフェースを定義する必要があります。

■■使いやすさ開発者にとって、インターフェースのすべてのメソッドを実装するよりも基本型から派生した新しい型を定義する方が一般的に簡単です。基本型は多くの機能を提供できるので、派生型はおそらくその動作に比較的小さな変更を加えるだけで済みます。インターフェースを提供する場合、新しい型はすべてのメンバーを実装しなければなりません。

■一貫性のある実装インタフェース規約がどれほどうまく文書化されていても、誰もが100%正しくその規約を正しく実装することはめったにありません。実際、COM はこのまさしくその問題に苦しんでいます、それがいくつかのCOMオブジェクトが Microsoft WordまたはWindows Internet Explorerでのみ正しく機能する理由です。基本型に適切なデフォルト実装を提供することで、まずはうまく動作し、十分にテストされた型を使用します。修正が必要な部分は修正することができます。

■バージョン管理基本型にメソッドを追加すると、派生型は新しいメソッドを継承します。動作する型を使用することから始め、ユーザーのソースコードを再コンパイルする必要すらありません。インタフェースに新しいメンバを追加すると、インタフェースの継承者はそのソースコードを変更して再コンパイルする必要があります。

12
Deepak Mishra

インタフェースは、サービスまたはサービスセットの契約を定義します。 2つのクラスはインタフェースによって定義されたサービスのセットを満たすことを約束されているので、それらは水平の方法で多型を提供します。インタフェースは実装の詳細を提供しません。

抽象クラスは、そのサブケースの基本構造、およびオプションで部分的な実装を定義します。抽象クラスを継承するクラスは、その抽象クラスのインスタンスとして扱うことができますが、その逆はできません。抽象クラスは実装の詳細を含むことができますが、独自にインスタンス化することはできません。サブクラスだけを "新規作成"できます。

C#はインターフェースの継承も可能にします。

10
joelmdev

あなたは専門家から理論的な知識を得たかもしれないので、ここでそれらすべてを繰り返すことに多くの単語を費やすのではなく、むしろInterfaceAbstract classを使用できる/使用できない簡単な例で説明します。

あなたが車のすべての機能をリストするようにアプリケーションを設計していると考えてください。 DigitalFuelMeter、エアコン、座席調整などのプロパティのすべてがすべての車に共通しているので、さまざまな点であなたは共通の継承を必要とします。同様に、ブレーキシステム(ABS、EBD)などのプロパティの一部は一部の車にのみ適用されるため、一部のクラスにのみ継承が必要です。 

以下のクラスはすべての車の基本クラスとして機能します。

public class Cars
{
    public string DigitalFuelMeter()
    {
        return "I have DigitalFuelMeter";
    }

    public string AirCondition()
    {
        return "I have AC";
    }

    public string SeatAdjust()
    {
        return "I can Adjust seat";
    }
}

それぞれの車に別々のクラスがあるとします。

public class Alto : Cars
{
    // Have all the features of Car class    
}

public class Verna : Cars
{
    // Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars        
}

public class Cruze : Cars
{
    // Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars        
}

私たちが車ヴェルナとクルーズのためにブレーキング技術を受け継ぐための方法を必要とすると考えてください(アルトには適用できません)。どちらもブレーキング技術を使用していますが、「技術」は異なります。そのため、メソッドがAbstractとして宣言され、その子クラスで実装される抽象クラスを作成します。

public abstract class Brake
{
    public abstract string GetBrakeTechnology();
}

今、私たちはこの抽象クラスから継承しようとしています、そしてブレーキシステムのタイプはVernaとCruzeで実行されます:

public class Verna : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }       
}

public class Cruze : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
       return "I use EBD system for braking";
    }         
}

上記の2つのクラスの問題を見てください。メソッドが子で実装されていても、C#.Netでは許可されていない複数のクラスを継承しています。ここでそれはインターフェースの必要性になります。

interface IBrakeTechnology
{
    string GetBrakeTechnology();
}

そしてその実装は以下の通りです。

public class Verna : Cars, IBrakeTechnology
{
    public string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }
}

public class Cruze : Cars, IBrakeTechnology
{
   public string GetBrakeTechnology()
   {
       return "I use EBD system for braking";
   }        
}

VernaとCruzeは、Interfaceを利用して独自の種類のブレーキテクノロジで複数の継承を実現できます。

10
Sarath Avanavu

ほとんどの答えは、抽象クラスとインターフェイスの技術的な違いに焦点を当てていますが、技術的には、インターフェイスは基本的に一種の抽象クラスです(データまたは実装)、私は概念の違いがはるかに興味深いと思います、そしてそれはインタビュアーが求めているものかもしれません。

Interfaceagreementです。 「これは、私たちがお互いに話し合う方法です」と明記しています。実装することは想定ではないため、実装することはできません。それは契約です。 Cの.hヘッダーファイルに似ています。

抽象クラ​​ス不完全な実装です。クラスはインターフェースを実装してもしなくてもよく、抽象クラスはそれを完全に実装する必要はありません。実装のない抽象クラスは無意味ですが、完全に合法です。

基本的に、クラスは抽象であろうとなかろうと、それはisであるのに対して、インターフェースは使用方法についてです。例:Animalは、いくつかの基本的な代謝機能を実装し、実装を行わずに呼吸と移動の抽象メソッドを指定する抽象クラスである場合があります。またはクロールします。一方、Mountは、動物の種類(または動物であるかどうか)を知らずに動物に乗ることができることを指定するインターフェイスである場合があります。

裏では、インターフェースは基本的に抽象メソッドのみを持つ抽象クラスであるという事実は重要ではありません。概念的には、まったく異なる役割を果たします。

10
mcv

インターフェースは特定の振る舞いを強制するための軽量な方法です。それが一つの考え方です。

9
fastcodejava

インタフェース型と抽象基底クラス

Pro C#5.0と.NET 4.5 Framework bookからの抜粋。

インタフェース型は抽象基本クラスに非常に似ているように見えるかもしれません。クラスが抽象としてマークされているとき、それはすべての派生型に多態的インタフェースを提供するために任意の数の抽象メンバを定義できることを思い出してください。ただし、クラスが一連の抽象メンバーを定義する場合でも、任意の数のコンストラクター、フィールドデータ、(]実装を含む)非抽象メンバーなどを自由に定義できます。一方、インタフェースは抽象メンバ定義のみを含みます。抽象親クラスによって確立された多相インタフェースには、派生型のみが抽象親によって定義されたメンバをサポートするという大きな制限があります。 。しかし、より大きなソフトウェアシステムでは、System.Object以外に共通の親を持たない複数のクラス階層を開発することは非常に一般的です。抽象基底クラスの抽象メンバは派生型にのみ適用されるので、同じ多態性インタフェースをサポートするために異なる階層の型を構成する方法はありません。例として、次の抽象クラスを定義したとします。

public abstract class CloneableType
{
// Only derived types can support this
// "polymorphic interface." Classes in other
// hierarchies have no access to this abstract
// member.
   public abstract object Clone();
}

この定義では、CloneableTypeを拡張するメンバだけがClone()メソッドをサポートできます。この基本クラスを拡張しない新しいクラスのセットを作成した場合は、この多態性インターフェイスを入手することはできません。また、C#はクラスの多重継承をサポートしていないことを思い出すかもしれません。

// Nope! Multiple inheritance is not possible in C#
// for classes.
public class MiniVan : Car, CloneableType
{
}

ご想像のとおり、インターフェースの種類が役に立ちます。インターフェースが定義された後、それは任意のクラス、任意のネームスペースまたは任意のアセンブリ内の任意の階層の任意のクラスまたは構造、任意の.NETプログラミング言語で書かれたで実装することができます。ご覧のとおり、インターフェイスは非常に多態性が高いです。 System名前空間で定義されているICloneableという名前の標準的な.NETインターフェイスを考えてみましょう。このインターフェースはClone()という名前の単一のメソッドを定義します。

public interface ICloneable
{
object Clone();
}
6
Jahan

2番目の質問への回答:publicに定義されているinterface変数はデフォルトでstatic finalで、publicクラスのabstract変数はインスタンス変数です。

6
Nidhi Agarwal

1)インタフェースは純粋な抽象クラスと見なすことができ、同じですが、これにもかかわらず、インタフェースを実装し抽象クラスから継承するのと同じではありません。この純粋な抽象クラスから継承するときは、階層を定義しています - >継承、あなたがインターフェースを実装するのであればあなたはそうではなく、あなたは好きなだけインターフェースを実装できますが、1つのクラスからしか継承できません。

2)インタフェースでプロパティを定義できるので、そのインタフェースを実装するクラスはそのプロパティを持たなければなりません。

例えば:

  public interface IVariable
  {
      string name {get; set;}
  }

そのインタフェースを実装するクラスはそのようなプロパティを持たなければなりません。

6
MRFerocius

この質問はかなり古くからありますが、私はもう一つインターフェイスを支持する点を付け加えたいと思います。 

抽象クラス注入がほとんどサポートしていない場合は、任意の依存注入ツールを使用してインターフェイスを注入できます。

6
paragy

From もう1つの答え 、主に一方を他方に対して使用する場合の対処方法:

私の経験では、インターフェースは、同じメソッドに対応する必要があるいくつかのクラスがある場合に最もよく使用されます。それらのクラスの共通のインターフェースに対して書かれる他のコードと互換的に使用されます。インターフェースの最良の使用は、プロトコルが重要であるが基礎となる論理がクラスごとに異なる場合がある場合です。そうでなければ論理を複製することになる場合は、代わりに抽象クラスまたは標準クラス継承を検討してください。

5
Adam Alexander

コーディングの観点から

抽象クラスに抽象メソッドしかない場合、インタフェースは抽象クラスを置き換えることができます。そうでなければ、抽象クラスをインタフェースに変更することは、継承が提供するコードの再利用性を失うことを意味します。

デザインの観点から

"Is a"関係であり、サブセットの機能またはすべての機能が必要な場合は、抽象クラスとして保持してください。それが「するべきである」関係であるならば、インターフェースとしてそれを保ってください。

あなたが何を必要としているかを決定してください:ただポリシーの執行、あるいはコードの再利用性とポリシーです。

4
Vivek Vermani

OOPのインターフェースと抽象クラスの振る舞い(そして言語がそれらをどのように処理するか)を理解することは確かに重要ですが、各用語が正確に何を意味するのかを理解することも重要です。 ifコマンドが用語の意味どおりに機能しないと想像できますか?また、実際には、インターフェイスと要約の違いをさらに縮小している言語もあります。偶然にも2つの用語がほぼ同じように機能する場合は、少なくともどちらを使用するか(そしてなぜ)を定義できます。のために使用される。

いくつかの辞書や他のフォントを読むと、同じ用語に対して異なる意味があるかもしれませんが、いくつかの共通の定義があります。私は このサイトに で見つけたこれら2つの意味が本当に、本当によく、そして適切であると思います。

インタフェース: 

個別の、場合によっては互換性のない要素を効果的に調整できるようにするためのものまたは状況。

抽象: 

それ自体がより広範囲またはより一般的なもの、あるいはいくつかのものの本質的な特質に集中しているもの。エッセンス。 

例: 

あなたは車を買った、そしてそれは燃料を必要とする。 

enter image description here

あなたの車のモデルはXYZで、これはジャンルABCであるので、それは具体的な車であり、車の特定のインスタンスです。車は本物ではありません。実際、それは特定のオブジェクトを作成するための一連の抽象的な標準(品質)です。一言で言えば、車は 抽象クラス、それは 「もっと広範な、あるいはもっと一般的なものの本質的な性質をそれ自体に集中させるもの」。 

車のマニュアル仕様に一致する唯一の燃料を車のタンクを埋めるために使用する必要があります。実際には、燃料を補給することを制限するものは何もありませんが、エンジンは指定された燃料でのみ正常に動作するため、その要件に従うことをお勧めします。要件は、同じABCの他の車として、それが標準の燃料のセットを受け入れると言います。

オブジェクト指向のビューでは、ABCというジャンルの燃料はクラスとして宣言するべきではありません。特定の車種のジャンルには具体的な燃料がないためです。あなたの車は抽象クラスFuelまたはVehicularFuelを受け入れることができますが、あなたは既存の車両用燃料のあなたの唯一のいくつかが仕様を満たすことを覚えておかなければなりません。一言で言えば、彼らは実装する必要があります インタフェース ABCGenreFuel、 「...独立した、場合によっては互換性のない要素を効果的に調整することができます」。 

補遺

さらに、クラスという用語の意味を覚えておく必要があると思います(前述の同じサイトから)。

クラス:

共通の属性、特性、資質、または特性のためにグループを形成していると見なされる多数の人または物。種類;

このように、クラス(または抽象クラス)は共通の属性(インタフェースなど)だけを表すのではなく、共通の属性を持つある種のグループを表すべきです。インターフェースは種類を表す必要はありません。それは共通の属性を表現しなければなりません。このように、クラスと抽象クラスは、人間が哺乳類であるように、その側面を頻繁に変えてはいけないものを表すために使用できると思います。種類はそれほど頻繁に自分自身を変えるべきではありません。 

4
Felypp Oliveira

Interface:- == contract.Whicheverクラスは、インターフェースのすべての仕様に従う必要があります。

リアルタイムの例は、任意のISOとマークされたProduct .ISOは、製品のビルド方法とrules/specification it Mustが持つminimum set of featuresのセットを提供します。

これはsubset of properties product must have.ISOが製品only if it satisfies the its standardsに署名するだけです。

このコードを見てみましょう

public interface IClock{       //defines a minimum set of specification which a clock should have

    public abstract Date getTime();
    public abstract int getDate();
}
public class Fasttrack: Clock {
    // Must have getTime() and getTime() as it implements IClock
    // It also can have other set of feature like 
    public void startBackgroundLight() {
        // watch with internal light in it.
    }
    .... //Fastrack can support other feature as well
    ....
    ....
}

ここでは、it has all that features that a watch must suppost最小機能セット)であるため、Fastrackが監視として呼び出されます。

なぜ抽象的であるか:

MSDNから:

abstract classの目的は、複数の派生クラスが共有できるcommon definition of a base classを提供することです。

たとえば、クラスライブラリは、多くの関数のパラメータとして使用される抽象クラスを定義し、そのライブラリを使用するプログラマに、派生クラスを作成してクラスの独自の実装を提供することを要求します。 Abstract simply means if you cannot define it completely declare it as an abstract。実装クラスはこの実装を完了します。

例:抽象クラスとしてRecipeクラスを宣言したが、どのレシピを作成するかわからない場合、このクラスを一般化してcommon definition of any recipeを定義します。レシピの埋め込みは依存しますディッシュの実装について

抽象クラスは、抽象メソッドだけでなく抽象メソッドでも構成できます。したがって、インターフェイスの違いに気付くことができます。実装クラスに必要なすべてのメソッドとは限りません。抽象メソッドをオーバーライドするだけです。

簡単な言葉でtight coupling use Interface o/w use in case of lose coupling Abstract Classが必要な場合

3
Dipak Ingole

他にもいくつか違いがあります。

抽象クラスは静的メソッド、プロパティ、フィールドなどと演算子を持つことができますが、インターフェイスはできません。

したがって、ほとんどの場合、(静的メンバーを介して)実装されていなくても抽象クラスを単独で使用できます。また、インターフェースを単独では使用できません。

3
Orlin Petrov

抽象クラスはクラスの機能を効率的にパッケージ化することを扱いますが、インタフェースは意図/契約/通信用であり、他のクラス/モジュールと共有されることになっています。 

契約と(部分)契約の実装者の両方として抽象クラスを使用すると、SRPに違反します。コントラクト(依存関係)として抽象クラスを使用すると、再利用性を向上させるために、複数の抽象クラスを作成することが制限されます。 

以下のサンプルでは、​​注文の処理として抽象クラスを使用すると、顧客の種類とカテゴリに基づいて注文を処理する方法が2つあるため、問題が発生します(顧客は直接または間接、金または銀)。したがって、インターフェースは契約に使用され、抽象クラスはさまざまなワークフローの実施に使用されます。

public interface IOrderProcessor
{
    bool Process(string orderNumber);
}

public abstract class CustomerTypeOrderProcessor: IOrderProcessor
{
    public bool Process(string orderNumber) => IsValid(orderNumber) ? ProcessOrder(orderNumber) : false;

    protected abstract bool ProcessOrder(string orderNumber);

    protected abstract bool IsValid(string orderNumber);
}

public class DirectCustomerOrderProcessor : CustomerTypeOrderProcessor
{
    protected override bool IsValid(string orderNumber) => string.IsNullOrEmpty(orderNumber); 

    protected override bool ProcessOrder(string orderNumber) => true; 
}

public class InDirectCustomerOrderProcessor : CustomerTypeOrderProcessor
{
    protected override bool IsValid(string orderNumber) => orderNumber.StartsWith("EX");

    protected override bool ProcessOrder(string orderNumber) => true;
}

public abstract class CustomerCategoryOrderProcessor : IOrderProcessor
{
    public bool Process(string orderNumber) => ProcessOrder(GetDiscountPercentile(orderNumber), orderNumber);

    protected abstract int GetDiscountPercentile(string orderNumber);

    protected abstract bool ProcessOrder(int discount, string orderNumber);
}

public class GoldCustomer : CustomerCategoryOrderProcessor
{
    protected override int GetDiscountPercentile(string orderNumber) => 15;

    protected override bool ProcessOrder(int discount, string orderNumber) => true;

}

public class SilverCustomer : CustomerCategoryOrderProcessor
{
    protected override int GetDiscountPercentile(string orderNumber) => 10;

    protected override bool ProcessOrder(int discount, string orderNumber) => true;

}

public class OrderManager
{
    private readonly IOrderProcessor _orderProcessor;// Not CustomerTypeOrderProcessor or CustomerCategoryOrderProcessor 

    //Using abstract class here would create problem as we have two different abstract classes
    public OrderManager(IOrderProcessor orderProcessor) => _orderProcessor = orderProcessor;
}
1
Saravanan

Abstract classInterfaceとの比較を除き、Abstract classConcrete classとの比較は意味があります。

具象クラスを使用するときは、抽象クラスを使用します除くあなたがインスタンス化したくない/インスタンス化できない拡張せずにそれらを使用します。そして、抽象メソッドを実装したくない、または実装できないメソッドを作成します。

類推が好きなら、クロムを抽象クラス(ブラウザとして使用できないためインスタンス化できない)、chromeおよびoperaをクロムから派生した具体的なクラスと考えてください。インターフェースとしてのブラウザーのアドオン構造。

インタフェース:

実装を含まないインターフェースは多数のインターフェースから継承することができる(多重継承をサポート)メンバーは自動的に公開されるプロパティ、メソッド、イベント、インデクサーを含むことができる

抽象クラス

実装が含まれている可能性があります。少なくとも1人のメンバは実装されません。クラスは単一のBaseクラスから継承することができます。 メンバーはアクセス修飾子を持つフィールド、プロパティ、コンストラクタ、デストラクタ、メソッド、イベント、インデクサを含むことができる

これらは抽象クラスとインタフェースの主な違いです。

0
Vishwas S L

これらの答えはすべて長すぎます。

  • インタフェースは動作を定義するためのものです。

  • 抽象クラスは、振る舞いも含めて、物事自体を定義するためのものです。そのため、インターフェイスを継承した追加のプロパティを持つ抽象クラスを作成することがあります。

これはまた、Javaがクラスの単一継承のみをサポートし、インタフェースに制限を設けない理由も説明しています。具体的なオブジェクトは異なるものになることはできませんが、異なる動作をすることがあります。

0
K.Miao