2011-12-12 7 views
3

Prenez l'exemple suivant. Il y a un objet que je veux utiliser, appelez-le Doodad. Les éléments Doodad ont mal implémenté la gestion des événements du navigateur. L'instanciation typique d'un Doodad serait Doodad someDoodad = new Doodad();. Évidemment, cela ne répond pas à mes besoins en raison de la mauvaise gestion des événements. Est-il approprié pour moi de passer outre la méthode onBrowserEvent(), comme ceci:Classes internes anonymes: Quand sont-elles (in) appropriées?

Doodad someDoodad = new Doodad() { 
@Override 
    public void onBrowserEvent(Event event) { 
     switch (DOM.eventGetType(event)) { 
      case Event.ONDBLCLICK: 
      case Event.ONFOCUS: 
      case Event.ONCLICK: 
       if (!isEnabled()) { 
        return; 
       } 
       break; 
     } 
     super.onBrowserEvent(event); 
    } 
}; 

Évidemment, cela est un exemple simple, mais quand pourrais-je pas voulez utiliser une classe interne anonyme? Est-il jamais explicitement interdit ou impossible?

Je vois beaucoup de réponses à la première question, mais aucune des réponses à ce jour ne répond à la seconde: Est-il jamais explicitement interdit ou impossible d'utiliser une classe interne anonyme?

+0

comme l'exemple ci-dessus, surtout, j'ai vu, dans les cas de manipulation d'événements. –

Répondre

6

Généralement, la meilleure utilisation des classes internes anonymes est lorsque vous ne souhaitez créer qu'une seule instance de l'implémentation spécifique de cette classe. Et quand la mise en œuvre est assez simple. Idéalement, il devrait contenir 1-2 lignes de code.

Dans votre cas, il est toujours OK bien que votre méthode onBrowserEvent() soit supérieure à 2 lignes.

+1

Pour être juste, OP a fait tout son possible pour transformer 2 lignes en 6 en utilisant une instruction switch au lieu d'une instruction if. – corsiKa

+0

@glowcoder Il est 6 lignes pour arriver au point: quand est-il approprié d'utiliser des classes internes anonymes. J'aurais pu tout aussi bien faire la même chose en deux lignes, mais je voulais voir des réponses liées à la longueur du code (usage pratique) ainsi qu'à l'utilisation fonctionnelle. –

+0

Je préfère ajouter des méthodes à enums. Dans ce cas, je définirais la méthode 'proceedBrowserEvent' et l'implémenterais pour chaque membre d'enum. Dans ce cas, l'écouteur devrait vraiment invoquer une méthode, donc ce sera une ligne longue. – AlexR

0

Mon avis:

Anonyme classes internes: rappel d'une fonction (de sorte que vous n'écrivez pas le code deux fois)

classes internes nommées: plusieurs fonctions de Callbacks (ou une classe que vous avez besoin seulement pour la logique interne de la classe parente)

1

Souvent, un écouteur d'événement est un morceau de code qui n'est pas très générique, mais qui est lié à un widget spécifique, un bouton, un champ de texte, etc. Dans un tel cas, le code n'a pas besoin d'être correctement exposé pour que le monde puisse le réutiliser. Il est plus facile de le définir là où il est utilisé, et c'est ce à quoi servent les classes internes anonymes. Ils permettent d'incorporer rapidement des morceaux de code dans une autre méthode, sans avoir à se soucier des noms de classes, des paquets, de la visibilité ou de la réutilisabilité.

Bien sûr, ce que vous pouvez faire avec les classes internes anonymes peut toujours être fait avec des classes autonomes appropriées. Mais il est plus logique de le faire de cette façon lorsque votre classe de gestion d'événements est assez générique (peut gérer beaucoup d'événements), est réutilisable, dynamique, ou plus généralement quand il est avantageux d'extraire le code de gestion d'événements du code définit l'élément générateur d'événement.

Je ne suis pas sûr de comprendre spécifiquement votre question, j'espère que cette information vous aidera à trouver votre réponse. N'hésitez pas à poser d'autres questions.

3

Les classes internes anonymes sont la syntaxe de Java pour créer des fermetures. Voici un exemple approximative:

interface Adder { 
    int add(int arg); 
} 

... 

Adder createAdder(int n) { 
    final int nf = n; 
    return new Adder() { 
     int add(int arg) { return arg + nf; } 
    } 
} 

Méthode createAdder crée ce qui est essentiellement une fonction à l'aide d'une fermeture pour capturer la valeur passée n. Les fermetures jouent un rôle important dans la programmation fonctionnelle qui tente de l'intégrer. C'est pourquoi tout le monde crie que nous avons besoin de "vraies" fermetures en Java (c'est-à-dire, en général, une meilleure syntaxe que dans mon exemple).

(Bien sûr, je ne réponds pas à la question posée, je pense que ce que je dis, c'est que les cours anonymes sont bons pour ce que j'ai décrit ci-dessus.pour presque tout le reste je créerais une classe interne nommée parce que si quelque chose est auto-documentant et est dans mon opinion plus facile à lire)

+2

La fermeture réelle ne demanderait pas que les variables capturées soient marquées comme finales ... – gizmo

+0

Oui, le fait que vous ayez besoin de les capturer manuellement est nul, mais c'est juste syntaxique, et non fonctionnel. –

1

Je suggérerais des classes anonymes quand il implémente une méthode et/ou est un demi plein d'écran .

Si l'anonyme a une partie de code non trivale, cela vaut la peine d'avoir une classe nommée IMHO.

+0

Qu'entendez-vous par «mauvaise gestion des événements»? –

+0

Dans le PO, j'ai mentionné que "Doodads ont une mauvaise gestion des événements." Disons qu'il gère mal les clics quand il a été désactivé. –

+0

Le fait que la classe soit nommée ou anonyme ne change rien à son comportement (Autre que la valeur par défaut 'toString') et si elle a un mauvais traitement des événements, elle aura toujours ceci si elle a été nommée. –

0

Je n'utilise qu'une classe interne anonyme lorsqu'elle contient une très petite quantité de code. Raison est IMO il encombre le code et le rend moins lisible.

S'il y a plus de code nécessaire, je préfère créer une nouvelle classe, l'extension de la classe de base (dans ce cas « Doodad() »

+0

Définir "une très petite quantité de code" ... –

+0

Votre exemple est ok pour moi, mais pas plus que cela et je serais enclin à créer une classe séparée. –

0

Dans votre exemple, vous voulez créer une classe séparée. Ceci est En raison de la raison pour laquelle vous remplacez la méthode, il y a une mauvaise gestion des événements du navigateur

Plus précisément, vous pouvez créer ces Doodads améliorés à différents endroits. Vous voudrez supprimer tous ces Doodads améliorés et utiliser la mise en œuvre appropriée, mais essayer de trouver tous vos Doodads anonymes peut être fastidieux ou difficile. séparer la classe nommée puis refactoriser cette classe sera facile.

En outre, la raison de votre amélioration du Doodad peut être auto-documentée si vous créez une classe distincte pour cela. Alors que si vous avez juste une classe anonyme, vous devrez écrire des commentaires ou laisser les futurs responsables deviner pourquoi vous avez fait ce que vous avez fait.

par ex.

public class ImprovedBrowserEventHandlingDoodad extends Doodad { 
    ... 
} 

Tout ce qui ressemble à une fermeture est normalement un bon candidat pour utiliser une classe anonyme

par exemple.

new Thread(new Runnable() { 
    @Override 
    public void run() { 
     doSomething(); 
    } 
}).start(); 

Vous voulez seulement faire quelque chose dans ce un ensemble spécifique de circonstances et il n'y a pas besoin de copier et coller le code ailleurs ou factoriser dans une méthode. Les gestionnaires d'événements pour les interfaces graphiques utilisent généralement des classes anonymes car leur utilisation est limitée à la manière dont l'interface graphique est conçue et il n'est pas nécessaire de créer une instance distincte du gestionnaire d'événements en dehors du composant spécifique qui l'utilise. Par exemple, lorsque vous passez la souris sur une barre de défilement, son apparence change généralement. Rien d'autre dans le programme provoquera cette modification et généralement le gestionnaire d'événement sera une paire de lignes indiquant à la barre de défilement de changer son apparence, par exemple. scrollbar.setMouseOverEffect(true);.

Questions connexes