abstractclass とinterface は、抽象クラス定義をサポートする Java 言語の 2 つのメカニズムです。これら 2 つのメカニズムが存在するからこそ、Java には強力なオブジェクト指向機能が与えられます。抽象クラス定義のサポートという点では、abstractclass とインターフェースには大きな類似点があり、相互に置き換えることもできるため、多くの開発者は抽象クラスを定義する際に、abstractclass とインターフェースの選択についてよりカジュアルに考えているようです。実際、この 2 つの間には依然として大きな違いがあり、それらの選択は、問題領域の性質の理解と、設計意図の理解が正しく合理的であるかどうかさえ反映します。この記事では、それらの違いを分析し、開発者に 2 つのどちらかを選択するための基準を提供します。
抽象クラスを理解する
Abstractclass とinterface はどちらも Java 言語で抽象クラスを作成するために使用されます (この記事の抽象クラスは abstractclass から翻訳されたものではなく、抽象本体を表し、abstractclass は Java 言語で抽象クラスを定義するために使用されるメソッドです)。区別することに注意してください) 定義、それでは抽象クラスとは何ですか、そして抽象クラスを使用するとどのようなメリットがあるのでしょうか?
オブジェクト指向の概念では、すべてのオブジェクトがクラスによって表現されることはわかっていますが、その逆は当てはまりません。すべてのクラスがオブジェクトの記述に使用されるわけではありません。クラスに特定のオブジェクトを記述するのに十分な情報が含まれていない場合、そのクラスは抽象クラスになります。抽象クラスは、問題領域の分析と設計から導き出された抽象的な概念を表すためによく使用されます。これらは、見た目は異なっていても本質的には同じである一連の特定の概念を抽象化したものです。たとえば、グラフィック編集ソフトウェアを開発する場合、問題領域には円や三角形などの特定の概念が存在しますが、それらはすべて形状の概念に属します。問題領域に存在する場合、それは抽象的な概念です。抽象概念には問題領域内に対応する具体概念がないため、抽象概念を表すために使用される抽象クラスをインスタンス化することができません。
オブジェクト指向の分野では、抽象クラスは主に型の隠蔽に使用されます。固定された一連の動作の抽象的な記述を構築できますが、この一連の動作には、可能な具体的な実装をいくつでも含めることができます。この抽象的な記述は抽象クラスであり、この可能な具体的な実装のセットは、可能なすべての派生クラスによって表されます。モジュールは抽象本体上で動作できます。モジュールは固定された抽象化に依存しているため、変更することはできませんが、同時に、このモジュールの動作はこの抽象化から派生することによって拡張することもできます。 OCP に詳しい読者は、オブジェクト指向設計の中核原則の 1 つである OCP (Open-ClosedPrinciple) を実現するには、抽象クラスが鍵であることを知っているはずです。
文法定義レベルから抽象クラスとインターフェイスを見る
文法レベルでは、Java 言語は抽象クラスとインターフェイスに異なる定義を提供します。この違いを示すために、Demo という名前の抽象クラスを定義する例を次に示します。
abstractclass を使用して Demo 抽象クラスを定義する方法は次のとおりです。
プログラミングの観点から見ると、abstractclass とインターフェイスの両方を使用して、「designbycontract」のアイデアを実装できます。ただし、具体的な使用方法にはまだいくつかの違いがあります。
まず、Java言語におけるabstractclassは継承関係を表しており、クラスは継承関係を一度しか利用できません。ただし、クラスは複数のインターフェイスを実装できます。おそらくこれは、Java 言語の設計者が Java の多重継承サポートを検討する際に考慮した妥協案です。
次に、abstractclass の定義で、メソッドのデフォルトの動作を割り当てることができます。ただし、インターフェイスの定義では、メソッドにデフォルトの動作を持たせることはできません。この制限を回避するにはデリゲートを使用する必要がありますが、これにより複雑さが増し、場合によっては多くの問題が発生します。
抽象クラスでデフォルトの動作を定義できないことには、メンテナンス上の問題が発生する可能性があるという別の重大な問題があります。なぜなら、後で新しい状況に適応するためにクラスのインターフェース (通常、abstractclass またはインターフェースで表されます) を変更したい場合 (例えば、新しいメソッドを追加したり、既存のメソッドに新しいパラメーターを追加したりするなど)、非常に面倒なことになるためです。かなりの時間がかかります (特に派生クラスが多い場合)。ただし、インターフェイスが abstractclass を通じて実装されている場合は、abstractclass で定義されているデフォルトの動作を変更するだけで済みます。
同様に、抽象クラスでデフォルトの動作を定義できない場合、同じメソッドの実装が抽象クラスのすべての派生クラスに表示され、「1 つのルール、1 つの場所」の原則に違反し、コードの重複が発生し、これも好ましくありません。今後のメンテナンスに向けてしたがって、abstractclass とインターフェイスのどちらを選択するかには十分に注意してください。
設計概念の観点から抽象クラスとインターフェイスを考察する 上記では主に、文法定義とプログラミングの観点から抽象クラスとインターフェイスの違いについて説明しています。これらのレベルの違いは比較的低レベルであり、本質的ではありません。このセクションでは、abstractclass とinterface の違いを別のレベル、つまり 2 つによって反映される設計概念から分析します。著者はこう信じている