抽象クラス、インターフェースの違い、およびそれらをいつ使用するか


15

最近、私は頭をOOPに巻きつけ始めました。そして今、抽象クラスとインターフェースの違いについて読むほど、混乱してしまいます。これまでのところ、どちらもインスタンス化できません。インターフェースは多かれ少なかれ構造的な青写真であり、スケルトンを決定し、抽象は部分的にコードを実装できることによって異なります。

私の特定の状況を通して、これらについてもっと学びたいです。背景情報をもう少し知りたい場合の最初の質問へのリンクは次のとおりです。新しいクラスに適した設計モデルは何ですか?

ここに私が作成した2つのクラスがあります。

class Ad {
    $title;
    $description
    $price;

    function get_data($website){  }

    function validate_price(){  }
 }


class calendar_event {
    $title;
    $description

    $start_date;

    function get_data($website){ //guts }

    function validate_dates(){ //guts }
 }

ご覧のとおり、これらのクラスはほぼ同じです。ここに示されているが、他の機能があるではないlike get_zip()save_to_database()私のクラスで共通しています。また、すべての一般的なメソッドと、もちろんそれらのクラスに固有のプロパティ(マイレージ、重量など)を持つ他のクラスのCarsとPetsを追加しました。

現在、DRYの原則に違反しており、複数のファイルにわたって同じコードを管理および変更しています。私は、ボート、馬、またはその他のようなクラスを増やすつもりです。

これは、インターフェイスまたは抽象クラスを使用する場所ですか?抽象クラスについて理解していることから、抽象クラスにすべての共通要素が組み込まれたテンプレートとしてスーパークラスを使用し、将来のクラスで特に必要な項目のみを追加します。例えば:

abstract class content {
    $title;
    $description


    function get_data($website){  }

    function common_function2() { }
    function common_function3() { }
 }


class calendar_event extends content {

    $start_date;

    function validate_dates(){  }
 }

または、インターフェイスを使用し、これらが非常に類似しているため、各サブクラスが整合性の理由で使用することを強制される構造を作成し、各クラスを担当するためにそのクラスをフレッシュするエンド開発者に任せます一般的な機能の詳細です。私の考えでは、特定のクラスのニーズに合わせて、いくつかの「共通」関数を将来調整する必要があるかもしれません。

上記のすべてにもかかわらず、抽象クラスとインターフェースの全体とその理由を誤解していると思われる場合は、この方向で考えることをやめ、適切な方法を提案するために、有効な答えを必ずしてください!

ありがとう!


オンラインには多くの良い例があります。これはそのうちの一つだと思います。javapapers.com/core-java/abstract-and-interface-core-java-2/…–
Siva

回答:


26

素人の言葉で:

インターフェースは、「できる/できる」タイプの関係用です。

抽象(および具象)クラスは、"is a"のような関係です。

これらの例を見てください:

class Bird extends Animal implements Flight;
class Plane extends Vehicle implements Flight, AccountableAsset;
class Mosquito extends Animal implements Flight;
class Horse extends Animal;
class RaceHorse extends Horse implements AccountableAsset;
class Pegasus extends Horse implements Flight;

BirdMosquitoおよびHorse です Animals。それらは関連しています。それらは、Animalのような一般的なメソッドを継承しeat(), metabolize() and reproduce()ます。これらのメソッドをオーバーライドして少し余分に追加することもありますが、Animalに実装されているデフォルトの動作を利用します。metabolizeGlucose().

Plane関連していないBirdMosquitoまたはHorse

FlightBirdおよびのような、異なる、無関係なクラスによって実装されPlaneます。

AccountableAssetまた、Planeおよびのような異種の無関係なクラスによって実装されRaceHorseます。

Horse Flightを実装していません。

クラス(抽象または具体)見るとわかるように、階層の構築に役立ち、コードを階層の上位レベルから下位レベルに継承できます。理論的には、階層が下にあるほど、行動はより専門化されますが、すでに世話をしている多くのことを心配する必要はありません。

一方、インターフェイスは階層を作成しませんが、特定のコンテキストで階層から抽象化できるように、階層全体で特定の動作を均質化するのに役立ちます。

たとえば、プログラムのグループの値を合計するかどうかにAccountableAssets関係なく、グループの値を設定できます。RaceHorsesPlanes


すごい。インターフェイスは、can do/can be treated as抽象クラスが基礎として機能する場所を課す機能の特定のセクションを提供します!
Abhiroj Panwar

13

2つの違いを認識しているように見えるので、論理的に答えを推測できます。

インターフェイスは共通のコントラクトを定義します。すべての動物がEat()、Move()、Attack()などの機能を共有するIAnimalと呼ばれるインターフェイスなど。これらはすべて同じ機能を共有しますが、すべてまたはほとんどの場合、達成方法が異なります(実装)それ。

抽象クラスは、共通の実装と、オプションで共通のコントラクトを定義します。たとえば、単純な電卓は、すべての基本的な論理演算子とビット演算子を実装する抽象クラスとして修飾でき、ScientificCalculator、GraphicalCalculatorなどによって拡張されます。

共通の実装がある場合は、どうしても拡張機能の抽象クラスに機能をカプセル化します。PHPの経験はほとんどありませんが、非定数フィールドを持つインターフェイスを作成できるとは思いません。インスタンスクラス間でフィールドが共通している場合、getterおよびsetterを介してフィールドへのアクセスを定義しない限り、Abstractクラスを使用する必要があります。

また、Googleで結果が不足していないようです。


3

長い話は短い。抽象クラスは、継承クラス内のメソッドのテンプレートを提供するという点でインターフェイスによく似ていますが、大きな違いがあります。-インターフェイスは、継承クラスに存在する必要があるメソッドの名前/タイプのみを定義します。クラスはメソッドの完全なデフォルトコードを持つことができ、詳細だけをオーバーライドする必要がある場合があります。-インターフェイスにはアクセス修飾子を使用できません。-インターフェイスにフィールドを含めることはできません。-クラスは複数のクラスを継承できませんが、複数のインターフェースを継承できます。-また、クラスは階層構造を提供するため、特定のクラスから派生したクラスのみが抽象クラスのガイドラインに従う必要があります:オブジェクト->特定のオブジェクト->非常に特定のオブジェクト。一方、インターフェースは誰でもどこでも継承できます。

私の意見では、抽象クラスはコードのデフォルト実装をすぐに提供できるという点でより一般的ですが、特定のクラスを標準化する必要がある大規模プロジェクトでは、インターフェースが便利になる可能性があります。

それが役に立てば幸いですが、このオンラインにはたくさんの情報があります、レオ


2
Classes cannot have multiple inheritance-JavaやC#のような言語には当てはまりますが、C ++には当てはまりません。
ロバートハーベイ

3

まず、インターフェイスと抽象クラスの両方を提供することが多いことを理解する必要があります。この理由と、2つのコアの違いは、異なるコードを再利用できるため、異なる問題を解決できるためです。

インターフェイスを使用すると、さまざまな実装でクライアントコードを再利用できます。get_data($ website)クラスのクライアントは、$ titleまたは$ descriptionの項目を気にしません。データをロードするようにコンテンツに指示したいだけです。異なる種類のコンテンツがあり、その中には$ descriptionが必要なものとそうでないものがある場合、子クラスの署名のみを指定するContentInterfaceクラスを提供できます。これで、クライアントは、どのように動作するかを正確に知ることなく、さまざまなコンテンツをいくつでも持つことができます。リスコフの置換原則は、このアイデアを研究するために約読むことは良いことです。ボブおじさんのこのトピックに関する執筆も好きです。インターフェイスは単体テストにとって非常に重要であり、インターフェイスを作成することは習得するのに良い習慣です。

抽象クラスを使用すると、共通の祖先を共有する一連のクラスで共通の実装の詳細を再利用できます。あなたの質問では、抽象クラスから実装を継承する理由をよく理解しているようです。基本クラスの内部に依存することは依然として危険です。カプセル化に違反し、基本クラスの特定の実装の詳細に依存する子を作成することは非常に簡単です。Template Methodパターンは、カプセル化に違反することなく、基本クラスを使用する方法の一般的で健康的な例を提供します。

したがって、私が示したように、クラス階層のクライアントにインターフェイスを提供することが多いため、クライアントコードに影響を与えることなく実装を安全に変更できます。これにより、クライアントは、インターフェイスを継承するモックオブジェクトを使用して単体テストを作成できます。また、共通のロジックを再利用したり、子クラスにセマンティクスを適用したりする抽象クラスも提供します。


3

違いはわずかですが、明確な違いです。インターフェースは多態的な動作に関するものです。抽象クラスは、再利用と多態的な動作に関するものです。

再利用と多態的な振る舞いに重点を置きたい場合は、抽象クラスを選択します。たとえば、異なるタイプの従業員は異なる規定を持っていますが、すべての従業員はいくつかの共通点を受け取ります。共通ベース抽象クラスで発現させることができるのでので、抽象クラスは、それを表現するのに適しているEmployeeと差が派生のようなクラスで実装することができるManagerか、Worker

多態的な動作のみに重点を置きたい場合は、インターフェースを選択します。インターフェースは、コントラクト、つまり、特定の動作に適合すると言うオブジェクトまたは階層に関するものです。たとえば、すべての従業員には休暇の準備がありますが、さまざまな種類の従業員にはさまざまな種類の引当があります。そのため、従業員の種類ごとに異なる休暇計算機が必要です。ここでは、すべてのタイプの従業員が異なる動作のLeaveCalculatorインターフェイスを実装できるため、インターフェイスが適切な選択Calculate()です。


-3
  1. 主な違いは、Javaインターフェースのメソッドは暗黙的に抽象的であり、実装できないことです。Java抽象クラスには、デフォルトの動作を実装するインスタンスメソッドを含めることができます。
  2. Javaインターフェイスで宣言された変数は、デフォルトではfinalです。抽象クラスには非最終変数が含まれる場合があります。
  3. Javaインターフェースのメンバーはデフォルトでパブリックです。Java抽象クラスは、private、protectedなどのクラスメンバーの通常のフレーバーを持つことができます。
  4. Javaインターフェースは、キーワード「implements」を使用して実装する必要があります。キーワード「extends」を使用して、Java抽象クラスを拡張する必要があります。
  5. インターフェイスは別のJavaインターフェイスを拡張できますが、抽象クラスのみが別のJavaクラスを拡張し、複数のJavaインターフェイスを実装できます。
  6. Javaクラスは複数のインターフェースを実装できますが、拡張できる抽象クラスは1つだけです。
  7. インターフェイスは絶対に抽象的であり、インスタンス化できません。Java抽象クラスもインスタンス化できませんが、main()が存在する場合は呼び出すことができます。
  8. Java抽象クラスと比較すると、Javaインターフェースは追加の間接参照を必要とするため低速です。
  9. Javaのインターフェイスと抽象クラスでは、インターフェイスで非抽象メソッドを作成できません。インターフェイスのすべてのメソッドはデフォルトでは抽象ですが、抽象クラスで非抽象メソッドを作成できます。
  10. Javaの抽象クラスとインターフェイスの違いは、インターフェイスはType宣言により適し、抽象クラスはコードの再利用と進化の観点により適しているということです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.