2017-09-22 7 views
0

J'ai le problème suivant:Ajouter ActionListener à objet inconnu

J'ai une fonction comme ceci:

public void addActionListenerObject(Object object) { 
    object.addActionListener(this); 
} 

Mon problème est le suivant: je besoin d'une solution où je peux passer un objet à la Fonction addActionListener en tant que paramètre. La liste peut être trouvé ici: https://docs.oracle.com/javase/tutorial/uiswing/events/eventsandcomponents.html

Y at-il un moyen de résoudre ce problème sans nombreuses instances?

Merci

+0

ce qui est 'this' définition de la classe? extends/implements quelles classes/interfaces? –

+0

'this' est un ActionListener – qry

Répondre

1

Tenue Signature

Si vous ne pouvez pas changer votre signature de la méthode (par exemple, si vous devez recevoir un Object et appelez addActionListener() s'il y a une telle définition de la méthode), une solution plus générale/robuste utiliserait Java Reflections pour vérifier si l'objet réel a une méthode addActionListener() définie, et l'appeler également par des réflexions. Cela semble une approche très hacky, de toute façon.

Changing Signature

Si vous pouvez modifier votre signature de la méthode, essayez d'utiliser AbstractButton (https://docs.oracle.com/javase/7/docs/api/javax/swing/AbstractButton.html#addActionListener(java.awt.event.ActionListener)), qui est la superclasse qui définit cette méthode pour JButton, JToggleButton et JMenuItem, par exemple (voir « Direct connus Sous-classes "et l'arbre de définition de classe pour savoir où les méthodes sont réellement fournies).

Cette seconde approche ne fonctionnera que s'il existe réellement une seule superclasse définissant la méthode. S'il y en a plus d'un, vous devrez vérifier les classes possibles en utilisant if-else structure et instanceof + distribution explicite (que vous pouvez conserver votre signature originale Object).

Si vous donnez plus d'informations sur votre problème d'origine (par exemple, pourquoi avez-vous besoin d'une telle méthode), nous serons probablement en mesure de trouver de meilleures approches.

+0

Donc l'approche avec AbstractButton est celle que j'ai déjà faite, mais elle ne couvre pas les autres objets. La méthode de réflexion est probablement la meilleure, mais la performance pourrait être un problème. J'ai besoin de la méthode pour emballer plusieurs Actionneurs d'Action dans un Libary par moi ... Pour être honnête, je pourrais juste l'utilisateur ajouter mon Object en tant qu'AssistantListener, mais il ne se sent pas bien. La structure if-else est probablement la meilleure approche ... – qry

+0

La méthode de réflexion est plus robuste, car toute classe tierce ou future qui implémente la méthode 'addActionListener (...)' fonctionnera sans changement de code. D'autre part, si la probabilité d'avoir besoin de la méthode pour être si robuste est faible (signifiant que l'utilisation probable sera avec un ensemble proche de classes, y compris AbstractButton, etc), et la maintenabilité du code et des performances sont des exigences plus importantes. d choisissez l'approche 'if-else'. Comme toujours, le meilleur choix dépendra de l'image globale de votre problème réel. ;) –

0

Qu'est-ce que vous cherchez est polymorphisme. Toutes les instances de type Component ont la méthode addActionListener. Changez la signature de votre méthode pour attendre un Component, pas un Object. Je pensais que addActioListener a été hérité de ComponentCe n'est pas. La méthode est ajoutée individuellement à chaque type de composant, sans classe parente.

+0

Le composant de classe n'a pas la fonction addActionListener. J'ai eu la même idée, mais je cherche le bon cours et je suis incapable de le trouver. – qry

+0

Voir ma modification. Votre meilleur pari est d'écrire des méthodes individuelles pour chaque type nécessaire. – Strikegently

1

Passez un entier interface fonctionnelle (> = Java 1.8 uniquement) si vous êtes autorisé à modifier la signature de addActionListenerObject:

 
public class Just { 
    private ActionListener actionListener; 
    public void addActionListener(ActionListener actionListener) { 
     this.actionListener = actionListener; 
    } 
    public void doIt() { 
     System.out.println("Hello"); 
     actionListener.actionPerformed(new ActionEvent(this, 3, "World")); 
    } 
} 

public class MyActionListener implements ActionListener { 
    public void addActionListenerObject(Consumer<ActionListener> consumer) { 
     consumer.accept(this); 
    } 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println(e.getActionCommand()); 
    } 
} 

De cette façon, les classes qui ajoutent l'auditeur d'action (dans mon exemple c'est Just) ne doit pas implémenter une interface.

utiliser:

 
Just just = new Just(); 

MyActionListener listener = new MyActionListener(); 
listener.addActionListenerObject(just::addActionListener); // Aha! 

just.doIt(); 

Cette impression:

 
Hello 
World