web-dev-qa-db-ja.com

リスナーとアダプターの違いは何ですか?

リスナーとアダプターを区別しようとしています。

それらはほとんど同じですが、リスナーではすべてのメソッドをインターフェースに実装する必要がありますが、アダプターを使用すると、必要なメソッドのみを実装するオプションがあるため、コードがよりクリーンで読みやすくなりますか?

また、アダプターは1つの実装のみでインスタンス化を可能にし、リスナーをインスタンス化することはできません。これは完全には理解していません。

誰かがどちらを使用するのがより良いか、そしてあなたが一方で行うことができるが他ではできないことを説明できますか?

22
orange

WindowListenerinterfaceであり、すべてのメソッドをoverrideに強制しますが、 WindowAdapterWindowListenerの実装であり、扱いたいメソッドだけをoverrideする必要があります。

WindowListenerWindowListenerをインスタンス化できないことを意味するインターフェイスですが、WindowAdapternew演算子を使用してインスタンス化できる具象クラスです。

WindowAdapterを使用すると、クラスは必要なメソッドのみをオーバーライドするため、コードがより明確になります。例えば:

WindowListener

public class CloseListener implements WindowListener {
    // im not interest  on this event, but still need to override it
    @Override
    public void windowOpened(WindowEvent e) {

    }
    // im not interest  on this event, but still need to override it    
    @Override
    public void windowClosing(WindowEvent e) {

    }

    @Override
    public void windowClosed(WindowEvent e) {
        System.exit(0);

    }
    // im not interest  on this event, but still need to override it    
    @Override
    public void windowIconified(WindowEvent e) {

    }
    // im not interest  on this event, but still need to override it
    @Override
    public void windowDeiconified(WindowEvent e) {

    }

}

WindowAdapter

アダプターを使用している間、コードはよりきれいです:

// at JFrame class
addWindowListener(new CloseListener());

// reusable Close Listener
public class CloseListener extends WindowAdapter {
    @Override
    public void windowClosed(WindowEvent e) {
        System.exit(0);
    }
}

または

addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosed(WindowEvent e) {
         System.exit(0);
     }
});

したがって、WindowAdapterを使用することをお勧めしますが、は使用しないでください。ただし、リスナーオブジェクトを作成するための便宜として、WindowAdapterとほぼ同じ2つのAPIが存在します。

編集:

WindowListenerinterfaceであるため、JFrameサブクラスで実装できます。

public class MainWindow extends JFrame implements WindowListener {
    // this is ok
}
public class MainWindow extends JFrame, WindowAdapter {
    // this is not allow
}

しかし、WindowAdapterでそれを行うことはできません。

31
Pau Kiat Wee

どちらでもすべてを行うことができますが、インターフェースから始めると、コードには多くの定型文が含まれます。試してみたら、きっと気づいたことでしょう。インスタンス化などに関するそのステートメントは、かなり複雑な言い方であり、多くの用語の混乱があります。あなたは書ける

c.addWindowListener(new WindowListener() {
  @Override public void windowActivated(WindowEvent arg0) { }
  @Override public void windowClosed(WindowEvent arg0) { System.exit(0); }
  @Override public void windowClosing(WindowEvent arg0) { }
  @Override public void windowDeactivated(WindowEvent arg0) { }
  @Override public void windowDeiconified(WindowEvent arg0) { }
  @Override public void windowIconified(WindowEvent arg0) { }
  @Override public void windowOpened(WindowEvent arg0) { }
});

またはあなたは書くことができます

c.addWindowListener(new WindowAdapter() {
  @Override public void windowClosed(WindowEvent arg0) { System.exit(0); }
});

どちらの場合もインスタンス化WindowListenerまたはWindowAdapterのどちらでもない— WindowListener/extend WindowAdapterを実装する匿名クラスを作成している。ただし、インターフェースを直接実装する場合は、すべてのメソッドを実装する必要があり、アダプタークラスを拡張する場合は、必要なものだけをオーバーライドできます。そのクラスには、Listenerの場合に記述しなければならないまさにこれらの空の実装がすでにあります。

8
Marko Topolnik

他の回答で扱われていない別の側面があります:APIの進化。アダプタクラス(インターフェースの空またはデフォルトの実装)を提供すると、インターフェースに新しいメソッドを導入するのが簡単になります。 APIがインターフェイスのみを提供する場合、クライアントはそれらを実装する必要があり、新しいメソッドがインターフェイスに追加されると、実装するすべてのクラスが機能しなくなります。ただし、デフォルトの実装が提供されている場合、クライアントは代わりにそれらを拡張する機会があります。これは、便利であることに加えて、新しいAPIバージョンへのアップグレードに役立ちます。 default methods of Java 8の場合、デフォルト/空の実装は重要性が低くなりましたが、古いバージョンでは便利かもしれません。

0
Katona

MouseAdapter、KeyAdapter、WindowAdapterなど、拡張可能なアダプタークラスがいくつかあるため、実際には必要のないメソッドの記述を回避できます。

インターフェースの重要な点は、不要なメソッドをすべて書き出す必要があることです。必要なメソッドをオーバーライドする方法として、アダプタクラスをさらにサブクラス化できます。

http://www.cafeaulait.org/course/week7/19.html

0
Arianule

リスナーは、ほとんどのインターフェイスメソッドを利用する場合に使用します。一部のメソッドのみを使用する必要がある場合は、アダプターのほうが優れているため、残りのメソッドをオーバーライドする必要はありません。

0