MouseAdapter Klasse nutzen wenn eigene Klasse bereits von anderer erbt

Hag2bard

Bekanntes Mitglied
Ich habe eine Klasse die von JPanel erbt und momentan das MouseListener Interface implementiert.

Java:
public class TilePanel extends JPanel implements MouseListener {

Nun benötige ich aber nicht alle Methoden des Interfaces. Dafür wäre die MouseAdapter Klasse ja eigentlich gut geeignet.

Java:
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Mache irgendwas");
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

Wie man sieht, habe ich hier etliche Methoden implementiert, die ich nicht benötige. Aber ich erbe bereits von JPanel also fällt die Idee mit der MouseAdapter Klasse ins Wasser.
Wie kann ich die Implementierung der unnötigen Methoden umgehen?
Kann ich ein eigenes Interface schreiben mit default Methoden?

Danke im Voraus
 
Kann ich ein eigenes Interface schreiben mit default Methoden?
Ja, das kannst du:
Java:
public interface MouseListenerWithDefaults extends MouseListener {
    default void mouseClicked(MouseEvent e) {}
    default void mousePressed(MouseEvent e) {}
    default void mouseReleased(MouseEvent e) {}
    default void mouseEntered(MouseEvent e) {}
    default void mouseExited(MouseEvent e) {}
}

public class TilePanel extends JPanel implements MouseListenerWithDefaults {
}
 
Vielen Dank, das default wollte nicht funktionieren, da ich ein Semikolon statt den geschweiften Klammern benutzt habe, jetzt funktioniert es wie ich es möchte.
 
Erstell doch einfach eine innere Klasse, die von MouseAdapter ableitet (bzw. eine MouseAdapter-Variable, die die Methoden überschreibt), Problem gelöst und außerdem hast du die Methoden des Listeners vom Rest getrennt.
Dass ein Component gleichzeitig Listener ist, ist mittlerweile überholt. Früher hat man das oft so gemacht, aber spätestens seit Lambda macht das keiner mehr. Außerdem schützt das vor Missbrauch und Fehlern.
Nehmen wir mal an, deine Listener-Methdeon ändern etwas an der Komponente. Nun könntest du deine Klasse als Listener für eine andere Komponente verwenden. In diesem Fall würde sich der Listener nur selbst ändern, nicht aber die andere Komponente.
 
Das ist eine Lambda Expression keine innere Klasse.


Eine innere Klasse ist so was hier.

Java:
public class OuterClass {
    //.....
    
    class InnerClass {   
        public void print() {
            System.out.println("InnerClass");
        }
    }  //end InnerClass
    
} // end  OuterClass
 
Was meinst du mit innerer Klasse? Meinst du so was wie:

okButton.addKeyListener(e -> {
doSomething();
}
Das wäre ein Lambda Ausdruck, ersetzbar durch eine anonyme Klasse. Eine anonyme Klasse . würde auch funktionieren oder eben eine innere Klasse, wie sie jw4456 als Beispiel genannt hat. Es gibt da viele Möglichkeiten, welche dir deine Probleme ersparen .


Java:
//anonym ohne Hilfsvariable
void init() {
    a.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            //...
        }
    });
}

// Über lokale Variable oder Instanzvariable
void init() {
    a.addMouseListener(myListener);
}

MouseListener myListener = new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
        //...
    }
}

//über innere Klasse

void init() {
    a.addMouseListener(new MyListener());
}

private class MyListener extends MouseAdapter {
    @Override
    public void mouseClicked(MouseEvent e) {
        //...
    }
}
 
Zuletzt bearbeitet:
Und am gescheitetesten wäre die Variante mit der inneren Klasse?
Mir geht es nicht nur um die Übersichtlichkeit meiner Klassen, ich möchte mein Projekt so programmieren, dass ein erfahrener Programmierer drüber schaut und nichts zu beanstanden hat.
Ich bin auf jeden Fall immer für Kritik, Erklärungen und Verbesserungsvorschläge offen. Dass meine Klasse eine Erweiterung eines Listeners ist, habe ich nicht als Problem gesehen.
Ich habe z.b. eine Klasse die von JFrame erbt und das KeyListener Interface implementiert. Das Objekt dieser Klasse gebe ich mit Hilfe der addKeyListener sämtlichen Komponenten mit, die im JFrame "sitzen", damit ich beim Klick auf diese Komponenten weiterhin den Listener verwenden kann. Wieso macht man das nicht (mehr)?

Vielleicht bekomm ich es noch besser erklärt:

Der Keylistener ändert Felder der TilePanel Klasse. Muss der KeyListener in der TilePanel Klasse sein?
 
Zuletzt bearbeitet:
Und am gescheitetesten wäre die Variante mit der inneren Klasse?
Mir geht es nicht nur um die Übersichtlichkeit meiner Klassen, ich möchte mein Projekt so programmieren, dass ein erfahrener Programmierer drüber schaut und nichts zu beanstanden hat.
Ich bin auf jeden Fall immer für Kritik, Erklärungen und Verbesserungsvorschläge offen. Dass meine Klasse eine Erweiterung eines Listeners ist, habe ich nicht als Problem gesehen.
Ich habe z.b. eine Klasse die von JFrame erbt und das KeyListener Interface implementiert. Das Objekt dieser Klasse gebe ich mit Hilfe der addKeyListener sämtlichen Komponenten mit, die im JFrame "sitzen", damit ich beim Klick auf diese Komponenten weiterhin den Listener verwenden kann. Wieso macht man das nicht (mehr)?

Vielleicht bekomm ich es noch besser erklärt:

Der Keylistener ändert Felder der TilePanel Klasse. Muss der KeyListener in der TilePanel Klasse sein?

Dem erfahrenen Programmierer ist vor allem die Übersichtlichkeit wichtig 🙂
Guter Code ist solcher, den man Jahre später noch verstehen kann. Übersichtlichkeit und Dokumentation sind das A und O.

Jede der genannten Methoden funktioniert. Abhängig von der Länge des Codes des Mauslistener würde ich aber vom direkten Zuweisen einer anonymen Klasse absehen, da sonst die Übersichtlichkeit verloren geht.
Sofern nur einmal verwendet, würde ich also eine innere Klasse vorschlagen. Falls mehrfach vewendet, ist auch eine Instanzvariable ganz praktisch, da legt man den selben Schmuh nicht mehrmals an.


@Jw45 Für einen Mauslistener/Mausadapter wird Lambda aber leider nicht funktionieren, da er mehr als eine Methode hat.
 
Ich kenne keinen anderen Listener.

Aber mit einem Funktionalen Interface was die beiden nicht benutzen Methoden abdeckt (überschreibt) sollte es mit einem Lambda gen.


Java:
@FunctionalInterface
public interface KeyRealeasedListener extends KeyListener {
    @Override
    default void keyPressed(KeyEvent e) {
    }
    @Override
    default void keyTyped(KeyEvent e) {
    }
}

component.addKeyListener((KeyRealeasedListener) e -> System.out.println("key "));
 

Zurück
Oben