43

Tiger2 つのクラスがあるとしましょう Aeroplane。この 2 つのタイプの共通点の 1 つは、スピードです。スーパークラスを作成し、そこからサブクラスをClassWithSpeed派生させるのは非論理的であることはわかっています。代わりに、メソッドを含むインターフェイスを作成し、それをおよびに実装することをお勧めします。わかりました。しかし、インターフェイスがなくても同じことができます。メソッドinと メソッドinを定義できます。唯一の (おそらく非常に大きな) 欠陥は、インターフェイス参照のオブジェクトに「到達」できなかったことです。AeroplaneTigerspeed()AeroplaneTigerspeed()Aeroplanespeed()TigerTigerAeroplane

私は Java と OOP の初心者ですが、誰かがインターフェイスの役割を説明してくれたらとてもありがたいです。乾杯!

4

12 に答える 12

74

これは:

public int howFast(Airplane airplane) {
    return airplane.speed();
}

public int howFast(Tiger tiger) {
    return tiger.speed();
}

public int howFast(Rocket rocket) {
    return rocket.speed();
}

public int howFast(ThingThatHasntBeenInventedYet thingx) {
    // wait... what? HOW IS THIS POSSIBLE?!
    return thingx.speed();
}

...

public int howFast(Mover mover) {
    return mover.speed();
}

ここで、戻ってこれらすべてのhowFast関数を将来変更する必要があると想像してください。

インターフェイスであろうとなかろうと、各クラスはメソッドを実装または継承する必要がありspeed()ます。インターフェイスを使用すると、これらの異なるクラスをより簡単に使用できます。それぞれが特定の方法で動作することが約束されているためです。を呼び出すspeed()と、 が返されるintため、可能なクラスごとに個別のメソッドを記述する必要はありません。

相対論的物理学のブレークスルーのために速度を別の方法で処理する必要がある場合は、 を呼び出すメソッドを更新するだけで済みますspeed()。あなたのひ孫娘が のクラスをHyperIntelligentMonkeyFish作成するとき、あなたのコードがミュータント軍を監視および制御できるように、古いバイナリを逆アセンブルして変更を加える必要はありません。彼女はそれを宣言するだけですHyperIntelligentMonkeyFish implements Mover

于 2013-05-26T16:15:53.707 に答える
6

次の例を使用して、インターフェイスの利点を説明しようとしています-

トラまたは飛行機をパラメーターとして使用する必要がある別のクラスがあるとします。したがって、インターフェースを使用することで、次を使用して呼び出すことができます

someObject.someMethod(ClassWithSpeed)

ただし、インターフェースを使用しない場合は、使用できます

someObject.someMethod(Tiger)
someObject.someMethod(AeroPlane)

今、あなたは何をすべきですか?あなたのありそうな答えは次のようになります。"I will use two overloaded method".

ここまでは大丈夫ですが、

さらにオプションを追加する必要があるとします (たとえば、車、自転車、ウサギ、カメなど 100 個)。では、既存のコードを変更するにはどうしますか?? いろいろ変える必要が出てきます..

上記の全体的な例の目的は 1 つだけです。つまり

「より優れた、再利用可能で適切なオブジェクト指向設計を作成するためのインターフェースが必要です」

注意

  1. プログラムが小さすぎて変更する必要がないと確信している場合は、インターフェースなしで実装しても問題ないと思います
于 2013-05-26T16:17:26.643 に答える
5

インターフェースを定義すると、Airplane と Tiger だけでなく、同じインターフェースを共有する他のクラスでも機能するメソッドを定義できます。

たとえば、インターフェイスが IObjectWithSpeed だとします。次に、IObjectWithSpeed オブジェクトで動作する単一のクラスで、このようなメソッドを定義できます。

  public double calculateSecondsToTravel( IObjectWithSpeed obj, double distance ) {
       return distance / obj.getSpeed();
  }

インターフェースを使用すると、オープン/クローズの原則を満たすことができます。拡張に対してはオープンですが、変更に対してはクローズです。IObjectWithSpeed を実装する新しいクラスが定義されているため、上記のメソッドの単一の実装を変更する必要はありません。

于 2013-05-26T16:14:10.090 に答える
3

インターフェイスは単なるメソッド シグネチャではありません。

契約を表す型です。メソッドの署名ではなく、コントラクトが重要です。クラスがインターフェイスを実装するのは、クラスが型として実装することに関心がある共有動作のコントラクトがあるためです。そのコントラクトは、通常はメソッド本体ですが、静的な最終フィールドを含む場合もある指定されたメンバーを介して実装されます。

トラと飛行機の両方が、speed() を介して実装される共通の動作を持つ型として表現できるのは本当かもしれません ... もしそうなら、インターフェイスはその動作を表現するためのコントラクトを表します。

于 2013-05-26T16:39:17.593 に答える
3

これらのクラスの機能を説明するだけでなく、インターフェースのメソッドは、それを実装するクラスについての知識がなくても、まだ定義されていないクラスであっても使用できます。

したがって、たとえば、Transport効率的なルートを計算するクラスが必要な場合ClassWithSpeedは、パラメーターとして実装するクラスを指定し、そのメソッドを使用しspeed()て必要なものを計算することができます。このようにして、クラスで使用できますがAeroplane、後で定義する任意のクラスでも使用できますBoat。Java は、クラスをパラメーターとして使用する場合Transportは を実装しClassWithSpeed、実装するすべてのクラスClassWithSpeedがメソッドを実装してspeed()使用できるようにします。

于 2013-05-26T16:21:05.053 に答える
1

インターフェイス (言語構成体として) は、メソッド呼び出しが有効であることを証明するためにコンパイラによって使用され、実装クラスに関する知識を最小限に抑えながら、依存クラスを実装クラスと対話させることができます。

于 2013-05-26T16:17:15.813 に答える
1

言語レベルでは、インターフェースの唯一の用途は、あなたが述べたように、共通の方法で異なるクラスを参照できるようにすることです。しかし、人々のレベルでは、状況は異なって見えます。IMO Java は、設計と実装が別の人 (多くの場合、別の会社) によって行われる大規模なプロジェクトで使用される場合に強力です。現在、システム アーキテクトは、Word 文書に仕様を記述する代わりに、実装者が IDE に直接挿入して作業を開始できる一連のクラスを作成できます。言い換えれば、「クラスXは目的Aに使用するためにメソッドYとZを実装する」と宣言する代わりに、単に「クラスXはインターフェースAを実装する」と言う方が便利です。

于 2013-05-27T07:00:25.773 に答える
1

代わりにコンポジションを使用してみましたか? 2 つの異なるクラスに同じ機能を継承させたい場合は、抽象クラスを使用してインスタンスをチェックすることにより、そのタイプのオブジェクトを受け取るクラスを使用します。インターフェイスは、クラスにメソッドを強制的に含めるが実装を必要としない場合や、2 つのコーダー チームが異なるコーディング領域で作業する場合に役立ちます。

Class Tiger {
  public MovingEntity mover;

 public Tiger(){

  mover.speed=30;
  mover.directionX=-1;
  mover.move(mover);

 }

}
Class Plane {
  public MovingEntity mover;

 public Plane(){
  mover.speed=500;
  mover.directionX=-1;
  mover.move(mover);

 }


Abstract Class Moverable(){
  private int xPos;
  private int yPos;
  private int directionX;
  private int directionY;
  private int speed;


Class MovingEntity extends Moverable {
 public void move(Moverable m){
   if(m instanceof Tiger){

      xPos+=directionX*speed;
      yPos+=directionY*speed;

   }else if(m instanceof Plane){
      xPos+=directionX*speed;
      yPos+=directionY*speed;

   }
 }
于 2013-05-27T08:30:13.280 に答える