リスナーとアダプターを区別しようとしています。
それらはほとんど同じですが、リスナーではすべてのメソッドをインターフェースに実装する必要がありますが、アダプターを使用すると、必要なメソッドのみを実装するオプションがあるため、コードがよりクリーンで読みやすくなりますか?
また、アダプターは1つの実装のみでインスタンス化を可能にし、リスナーをインスタンス化することはできません。これは完全には理解していません。
誰かがどちらを使用するのがより良いか、そしてあなたが一方で行うことができるが他ではできないことを説明できますか?
WindowListener はinterface
であり、すべてのメソッドをoverride
に強制しますが、 WindowAdapter はWindowListener
の実装であり、扱いたいメソッドだけをoverride
する必要があります。
WindowListener
はWindowListener
をインスタンス化できないことを意味するインターフェイスですが、WindowAdapter
はnew
演算子を使用してインスタンス化できる具象クラスです。
WindowAdapter
を使用すると、クラスは必要なメソッドのみをオーバーライドするため、コードがより明確になります。例えば:
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) {
}
}
アダプターを使用している間、コードはよりきれいです:
// 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が存在します。
編集:
WindowListener
はinterface
であるため、JFrameサブクラスで実装できます。
public class MainWindow extends JFrame implements WindowListener {
// this is ok
}
public class MainWindow extends JFrame, WindowAdapter {
// this is not allow
}
しかし、WindowAdapter
でそれを行うことはできません。
どちらでもすべてを行うことができますが、インターフェースから始めると、コードには多くの定型文が含まれます。試してみたら、きっと気づいたことでしょう。インスタンス化などに関するそのステートメントは、かなり複雑な言い方であり、多くの用語の混乱があります。あなたは書ける
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
の場合に記述しなければならないまさにこれらの空の実装がすでにあります。
他の回答で扱われていない別の側面があります:APIの進化。アダプタクラス(インターフェースの空またはデフォルトの実装)を提供すると、インターフェースに新しいメソッドを導入するのが簡単になります。 APIがインターフェイスのみを提供する場合、クライアントはそれらを実装する必要があり、新しいメソッドがインターフェイスに追加されると、実装するすべてのクラスが機能しなくなります。ただし、デフォルトの実装が提供されている場合、クライアントは代わりにそれらを拡張する機会があります。これは、便利であることに加えて、新しいAPIバージョンへのアップグレードに役立ちます。 default methods of Java 8の場合、デフォルト/空の実装は重要性が低くなりましたが、古いバージョンでは便利かもしれません。
MouseAdapter、KeyAdapter、WindowAdapterなど、拡張可能なアダプタークラスがいくつかあるため、実際には必要のないメソッドの記述を回避できます。
インターフェースの重要な点は、不要なメソッドをすべて書き出す必要があることです。必要なメソッドをオーバーライドする方法として、アダプタクラスをさらにサブクラス化できます。
リスナーは、ほとんどのインターフェイスメソッドを利用する場合に使用します。一部のメソッドのみを使用する必要がある場合は、アダプターのほうが優れているため、残りのメソッドをオーバーライドする必要はありません。