8

たとえば、不動産ビルダーは多くのアパートを備えたアパートを建設しています。寝室を除いて、アパートのすべての部屋は同じデザインです。ベッドルームのデザインは、アパートを所有する人々のために残されています。ベッドルームは、フラットごとに異なるデザインにすることができます。

abstract私は以下のようなクラスを通してこれを達成することができます:

public abstract class Flat
{
    //some properties

    public void livingRoom(){
       //some code
    }

    public void kitchen(){
       //some code
    }

    public abstract void bedRoom();

    }
}

implementationクラスは次のようになります。

public class Flat101 extends Flat
{
    public void bedRoom() {
        System.out.println("This flat has a customized bedroom");
   }        

}

interfaceまたは、クラスの代わりにabstract次のような同じ目的を達成するために使用できます。

class Flat
{
  public void livingRoom(){ 
       System.out.println("This flat has a living room");
  }

  public void kitchen(){
     System.out.println("This flat has a kitchen");
  } 
}

interface BedRoomInterface
{
  public abstract void bedRoom();
}

public class Flat101 extends Flat implements BedRoomInterface
{
   public void bedRoom() {
    System.out.println("This flat has a customized bedroom");
   }
}

ここでの質問は次のとおりです。このために、なぜinterface(または)abstractクラスを使用することを選択する必要があるのですか?

4

6 に答える 6

6

それはあなたの意図やユースケースに依存します。ただし、一般的には、抽象クラス(BlochのEffective Javaの項目18)よりもインターフェースを優先する必要があります。誰かが抽象クラスを変更して、そこから拡張する他のクラスの動作を変更する可能性があるため、抽象クラスはより脆弱です(これは一般的なステートメントです)。

BedroomInterfaceとLivingRoomInterfaceがある場合は、FlatInterfaceで両方のインターフェイスを実装でき、Flat101実装クラスでFlatInterfaceを実装できるため(Flatから拡張してインターフェイスを実装する代わりに)、インターフェイスを操作する方が柔軟性があります。これはより明確に思えます。後で、寝室と居間だけでなく、部屋を推測するExecutiveFlatInterfaceを使用して、Flat102を実装できます。

オプション2は、Flat101をFlatから拡張することです。次に、FlatはBedroomInterfaceとLivingRoomInterfaceを実装します。これは、実際に何をしたいか、どのような方法が必要になるかによって異なります。

于 2012-08-25T05:14:51.347 に答える
4

広く使用されるAPIを設計する場合は、クラスを実装することで満たされるコントラクトを表現するインターフェイスと、そのインターフェイスを部分的に実装してコードの再利用を可能にする抽象クラスの両方を使用します。 。

例として、JavaのListを考えてみましょう。Collectionsフレームワークのメソッド(Collections.sort()など)は、抽象クラスAbstractListによって部分的に実装され、具体的な実装LinkedListに拡張されたListインターフェイスで記述されています。およびArrayList。LinkedListとArrayListは、AbstractListのコードを再利用しますが、それでも、誰かがListの完全に別個の実装を記述し、Collections.sort()を使用してソートすることを妨げることはありません。

とはいえ、多くの状況では、このアプローチはやり過ぎになる可能性があります。構築している型階層が比較的小さなスコープ内でのみ使用される場合、抽象クラスを使用するだけで一般的には問題ありません。後でインターフェースが必要だと判断した場合は、物事を変更するための非常に簡単なリファクタリング作業です。

抽象クラスにはいくつかの利点があります。

  • パッケージ/保護された修飾子を使用して抽象メソッドを指定できます
  • コードの再利用を容易にします
  • スーパークラスで抽象メソッドとfinalメソッドを使用することで、クラスをサブクラス化する方法を制限できます。これは、さまざまな状況で役立ちます(テンプレートパターンも参照)。
  • クラスを参照するコードは、一般的にIDEで追跡するのが簡単です(抽象クラ​​スタイプパラメーターで[宣言を開く]をクリックすると、通常、インターフェイスタイプパラメーターよりも便利です)
于 2012-08-26T04:59:12.403 に答える
1

派生クラスに必要な機能の一部を提供するクラスがあるが、各派生クラスが他の機能の異なる実装をさらに必要とする場合、抽象クラスは、派生クラスに必要な特定の動作を残しながら、共通の実装を定義する手段を提供します各派生クラスに固有のものにします。

于 2012-08-25T15:13:01.113 に答える
0

一般化の手段だと思います。抽象クラスは、クラスのプロパティと動作が特定のパッケージまたはモジュール間で共通している場合に最も役立ちます。良い例の 1 つがドラム ブレーキです。すべてのドラム ブレーキは、ホイール ドラム内でブレーキを保持するのと同じように機能するため、この動作は、ドラム ブレーキを使用するすべてのクラスの車に継承できます。

インターフェイス用。それは、スペシエーションの実装を強制する仕様または契約に似ています。建物のモデルの例を見てみましょう。ドア、窓、エレベーターなどのすべての仕様があります。..しかし、モデルを実際の建物に実装する間、窓を維持する必要がありますが、内部の動作は (未亡人ができるように) によって決定されます。シンプルなウィンドウまたはスライダーウィンドウ、色と素材…)

お役に立てれば!!

于 2013-11-14T09:36:17.163 に答える
0

複数のクラスに共通の機能と抽象機能を実装する必要がある場合は、抽象クラスを使用する必要があると思います。いくつかの共通設計といくつかのカスタム設計があるフラットの例を見ると、そのようなユースケースでは、カスタム関数を実装するためにインターフェイスを再度使用するよりも抽象を使用する方が良いです。通常の派生クラスとして追加のインスタンス。

于 2015-09-18T06:13:10.347 に答える
-3

複数のクラスを拡張することはできませんが、複数のインターフェースを実装することはできます

設計を頻繁に変更する必要がある場合は、抽象クラスで変更が発生し、サブクラスで強制的に実装する必要がないため、抽象クラスの方が適しています。ただし、インターフェイスに変更があった場合は、実装クラスを実装する必要があります。

于 2012-08-25T05:19:39.427 に答える