インターフェイスと抽象クラスの使用の違いは、言語自体による強制というよりも、コードの編成に関係しています。他の開発者が使用するコードを準備して、意図した設計パターン内にとどまるようにするときに、これらをよく使用します。インターフェイスは一種の「契約による設計」であり、アクセスできないコードから発生する可能性のある所定の API 呼び出しのセットにコードが応答することに同意します。
抽象クラスからの継承は「is a」関係ですが、それが常に必要なわけではなく、インターフェイスの実装は「as like a」関係に近いものです。この違いは、特定のコンテキストでは非常に重要です。
たとえば、抽象クラス Account があり、そこから他の多くのクラス (アカウントの種類など) が拡張されているとします。そのタイプ グループにのみ適用できる特定のメソッド セットがあります。ただし、これらのアカウント サブクラスの一部は、Versionable、Listable、または Editable を実装しているため、これらの API を使用することを期待するコントローラーにスローできます。コントローラはオブジェクトのタイプを気にしません
対照的に、User 抽象クラスなど、Account から拡張されないオブジェクトを作成し、Listable および Editable を実装することもできますが、Versionable は実装できません。これはここでは意味がありません。
このように、FooUser サブクラスはアカウントではなく、編集可能オブジェクトのように機能すると言っています。同様に、BarAccount は Account から拡張されますが、User サブクラスではありませんが、Editable、Listable、および Versionable を実装します。
Editable、Listable、Versionable のこれらすべての API を抽象クラス自体に追加すると、雑然として醜いだけでなく、Account と User の共通インターフェイスが複製されるか、User オブジェクトに Versionable を強制的に実装させて、おそらく単に例外。