web-dev-qa-db-ja.com

インターフェイスと抽象メソッドのみを持つ抽象クラスの間に違いはありますか?

抽象クラスがあり、このクラスに抽象メソッドのみがあるとします。この抽象クラスは、同じメソッドのみを持つインターフェースとは異なりますか?

私が知りたいのは、抽象的メンバーのみを持つ抽象クラスと同等のインターフェイスの間で、哲学的、客観的、および基礎となるプログラミング言語の実装に違いがあるかどうかです。

9
yfklon

技術的には、違いはそれほど重要ではありませんが、概念的には完全に異なるものであり、それが他の人が述べた技術的な違いにつながります。

抽象スーパークラスはまさにそれがどのように聞こえるかであり、それは猫や犬は動物であるなど、他の多くの型によって共有される共通の型です。

インターフェースは、それがどのように聞こえるかということでもあります。それは、他のクラスがオブジェクトと通信できるインターフェースです。 Catウォークを作成する場合は、問題ありません。CatがCanWalkインターフェイスを実装しているからです。トカゲも同じですが、歩く方法は大きく異なります。一方、スネークはCanWalkを実装していないため、ウォークするように指示することはできません。一方、LizardとSnake(またはおそらくもっと明示的なサブクラス-私はエキスパートではない)は両方ともスキンを取り除き、したがってCanShedを実装するかもしれませんが、Catはそれができませんでした。

しかし、それらはすべて動物であり、生きているか死んでいるかなど、いくつかの共通の特性があります。

これが、インターフェイス上のすべてのメソッドをパブリックとして(または明示的にC#で)実装する必要がある理由です。オブジェクトとのインターフェースをとるクラスから隠されているインターフェースのポイントは何ですか?また、言語が複数の継承をサポートしていない場合でも、オブジェクトへの複数のインターフェイスを使用できるのはこのためです。

質問に戻ると、このように見ると、完全に抽象的なスーパークラスを持つ理由はほとんどありません。

22
pdr

ほとんどのOOP言語では、実装クラスは1つの抽象クラスからのみ派生できますが、複数のインターフェースを実装します。

19
herzmeister

多重継承を可能にし、インターフェースを持たないC++のような言語では、すべてのメソッドが抽象である抽象クラスをインターフェースとして使用できます。私はC++をあまり扱っていませんが、基本クラスに同じ名前のメソッドがある場合、多重継承が問題を引き起こす可能性があると思います。

PHPやC#などの言語では、抽象クラスの継承とインターフェイスの実装に概念的な違いがあるため、「継承」と呼ぶのは嫌いですが、インターフェイスは同様のポリモーフィズムを実現する手段を提供します。インターフェイスの削除それら自体は実装を提供しないため、競合の問題。

抽象クラスは実装を提供することができますが、インターフェイスを「偽造」するために使用した場合、それはほとんどの場合そうではありませんが、インターフェイスは外部の世界へのコントラクトとして機能します。

主な概念上の違いは、クラスが別のクラスを継承する場合(抽象かそうでないか)に「is」の関係があるため、CarVehicleであり、DogAnimalです。インターフェースでは、それが重要なのはオブジェクトが行うことです。したがって、CarDogの両方がMove()を実行でき、消費者はMovableを実装しているのでそれを知っていますが、CarはDogAnimalではありません。また、移動の実装は異なります(ホイールとレッグ)が、使用するコードでは気になりませんし、気にする必要もありません。インターフェースは、実装というよりも、消費するコードに関するものです。

重要な点は、選択した言語のインターフェイスがある場合、それらを使用するためにそれらを使用することです。そうでない場合(C++のように)、純粋な抽象クラスを使用してそれらを偽造できます。

3
Ivan Pintar

抽象クラスは、(私が使用している言語で)抽象保護メソッドを備えている場合があります。インターフェースでは、メソッドは通常常にパブリックです。この違いが有用な悪用を許可するかどうかはわかりません。

編集最初にプライベート抽象メソッドは役に立たないと思っていましたが、そのメソッドが呼び出されないようにするために使用できることを思い出しました。このようにして、オブジェクトのコピーコンストラクターが呼び出されるのを防ぐことができます。

2
Thomas

主な違いは次のとおりです。抽象クラスでは、すべてのメソッドがすべて抽象であっても、データメンバー(インスタンス変数)とそれを実装するクラスに(プライベートメソッドまたはコンストラクターの形式で)コードを提供できます。静的ブロック;サブクラスの作業の一部を行い、実装を支援します。

1つの肯定的な副作用:コードが1か所にあるため、1か所で修正できます。サブクラスは、スーパークラスのメソッドを呼び出すだけで、スーパークラスのアクションで十分であれば、他のことを実行するか、何も実行できません。スーパークラスは各サブクラスがこの決定をすることを望んでいるので、すべての実装を抽象としてマークしました(一部は空である可能性もあります)

質問には関係ありませんが、インターフェイスがあるということは、1つのクラスが2つの異なるコントラクトを実装できることを意味します。それが抽象スーパークラスに対するインターフェースの利点です

2
tgkprog

はい、違います。そうでなければ、言語デザイナーは両方を提供しなかっただろう。クラスとインターフェイスを分離する2つの言語を知っています:JavaとC#、Javaの変異クローンです。デザイナーは複数のクラスの継承をサポートしないようにインターフェイスを作成しました。他のほとんどの言語は複数のクラスの継承をサポートしているため、クラスとインターフェースを分離しないでください。

2
kevin cline