Anonymous vs nommé interne des classes? - les meilleures pratiques?

j'ai une classe, appelons-la LineGraph, traçant un graphique linéaire. J'ai besoin de sous-classe, mais la classe dérivée n'est utilisé que dans un seul endroit et est couplé à la classe qui l'utilise. Donc je suis en utilisant un intérieur de classe.

je vois deux façons de le faire:

Anonyme intérieur de la classe

public class Gui {
    LineGraph graph = new LineGraph() {
        // extra functionality here.
    };
}

Classe intérieure dénommée

public class Gui {
    MyLineGraph graph = new MyLineGraph();

    private class MyLineGraph extends LineGraph {
        // extra functionality here.
    }
}

Je ne suis pas un fan des classes intérieures anonymes, parce que franchement je pense que ça a l'air vraiment moche. Mais dans le cas d'une sous-classe qui n'est utilisée qu'à un seul endroit, est-ce qu'une classe interne nommée est exagérée? Quelle est la pratique acceptée?

41
demandé sur Joe Attardi 2009-04-03 20:06:12

15 réponses

l'un des avantages des classes intérieures Anonymes est que personne ne peut jamais l'utiliser ailleurs, alors qu'une classe intérieure nommée peut être utilisée (ne serait-ce que par la classe qui l'a créée si elle est rendue privée). C'est une petite différence, mais cela signifie que vous pouvez protéger un intérieur classe d'être accidentellement utilisé ailleurs.

aussi, en utilisant la classe interne anonyme donne à quiconque lisant votre code une tête - " cette classe est utilisée juste ici et nulle part ailleurs."Si vous voyez un nommé classe intérieure, quelqu'un pourrait penser qu'il serait utilisé dans plusieurs endroits de la classe.

ils sont très similaires, donc aucun point n'est un changeur de jeu. Je pense juste que ça aide pour la clarté si vous utilisez les classes internes anonymes pour les classes uniques, et les classes internes nommées quand elles sont utilisées plusieurs fois dans la classe.

48
répondu Daniel Lew 2009-04-03 16:12:17

(Contre-point à Daniel Lew)

l'un des inconvénients des classes intérieures Anonymes est que personne ne peut jamais l'utiliser ailleurs, alors qu'une classe intérieure nommée peut être utilisée (ne serait-ce que par la classe qui l'a créée si elle est rendue privée). C'est une petite différence, mais cela signifie que vous pouvez vous assurer que l'intérieur de la classe n'est pas accidentellement recréé ailleurs.

aussi, l'utilisation de la classe interne anonyme donne à quiconque lisant votre code un moment plus difficile que ils ont ensuite analyser cette classe qui est venu de nulle part. En utilisant une classe interne nommée, vous êtes en mesure d'organiser la source plus.

j'ai vu des cas où il y a deux (ou plus) classes intérieures anonymes avec le même code exact. Dans GUIs en particulier (où vous pouvez avoir plusieurs contrôles effectuer la même action) cela peut apparaître (et je parle de code de production, pas de code que mes étudiants ont écrit).

la question de la lisibilité va dans les deux sens, certaines personnes trouvent que les classes intérieures anonymes sont mieux car elles vous permettent de voir ce qui se passe dans un endroit, d'autres trouvent que c'est une distraction. La partie se résume à la préférence personnelle.

aussi rendre une classe statique est plus efficace, si vous déclarez une classe interne anonyme dans une instance alors il y aura plus de frais généraux, ce qui, si vous n'avez pas besoin d'accéder aux variables d'instance, est inutile (mais ne vaut probablement pas la peine de s'inquiéter jusqu'à ce qu'il se présente comme un problème).

ma préférence personnelle est d'utiliser des classes non-anonymes car elles permettent plus de flexibilité quand le code est modifié plus tard.

36
répondu TofuBeer 2009-04-03 16:41:59

Pourquoi devez-vous le classer? Si c'est juste pour passer outre une méthode virtuelle existante, je pense qu'une classe interne anonyme est acceptable. Si vous ajoutez des fonctionnalités supplémentaires, j'utiliserais une classe nommée. J'en ferais une classe imbriquée (i.e. avec le modificateur static ) - je les trouve plus faciles à raisonner sur:)

9
répondu Jon Skeet 2009-04-03 16:11:16

Faire la chose la plus simple qui pourrait éventuellement fonctionner : Utilisation de l'anonyme intérieur de la classe.

si vous constatez plus tard que vous avez besoin d'une portée plus large, alors reformuler le code pour le soutenir.

(vous feriez la même chose avec les variables -- les mettant dans la portée la plus spécifique. Il est logique de faire la même chose avec d'autres actifs de source.)

7
répondu Jeff Grigg 2009-04-03 18:37:54

les classes internes anonymes sont difficiles à déboguer dans Eclipse (c'est ce que j'utilise). Vous ne pourrez pas regarder des valeurs variables/injecter des valeurs en cliquant simplement avec le bouton droit de la souris.

4
répondu Kapsh 2009-04-03 16:30:49

un inconvénient des classes intérieures est qu'elles ne peuvent pas être statiques. Cela signifie qu'il y aura une référence à la classe extérieure qui les contient.

les classes intérieures Non statiques peuvent poser problème. Par exemple, nous avons récemment eu une classe intérieure étant sérialisé, mais la classe extérieure n'était pas sérialisable. La référence cachée signifiait que la classe externe serait aussi sérialisée, ce qui a évidemment échoué, mais il a fallu un certain temps pour découvrir pourquoi.

Où I le travail, les classes intérieures statiques sont encouragés dans nos meilleures pratiques de codage (si possible) car ils transportent moins de bagages cachés et sont plus maigres.

3
répondu user15299 2009-04-03 17:11:21

ma règle de base personnelle: si la classe interne anonyme va être petite, s'en tenir à une classe anonyme. Petit étant défini comme environ 20 à 30 lignes ou moins. S'il va être plus long, il commence à être illisible à mon avis, donc je fais un nommé classe intérieure. Je me souviens d'avoir vu une classe interne anonyme de plus de 4000 ans.

3
répondu Avrom 2009-07-30 18:55:23

les classes intérieures anonymes seraient généralement la voie à suivre. Je les trouve très lisible. Cependant, si l'instance de cette classe doit être sérialisée (même si ce n'est que parce que c'est un champ d'autre chose), je recommande fortement d'utiliser les classes internes nommées. Les noms des classes internes anonymes dans le bytecode peuvent changer très facilement, et ceci peut casser la sérialisation.

2
répondu Adam Crume 2009-04-03 16:35:38

les classes anonymes ne peuvent pas avoir de constructeur, puisqu'elles n'ont pas de nom. Si vous avez besoin de passer d'autres variables que celles du ou des constructeurs de la classe que vous étendez, vous devez utiliser une classe(statique) nommée inner class. Cela peut parfois être surmonté en utilisant des variables finales dans la méthode/code environnant, mais c'est un peu laid imho (et peut conduire à ce que Robin a dit).

2
répondu druidu 2010-11-20 04:15:44

Je n'ai pas de problème avec les cours anonymes simples. Mais s'il se compose de plus de quelques lignes de code ou de quelques méthodes, une classe intérieure est plus claire. Je pense également que, sous certaines conditions, elles ne devraient jamais être utilisées. Comme quand ils doivent retourner des données.

j'ai vu le code où un tableau final d'un élément est utilisé pour transmettre les données d'un appel à une classe interne anonyme. À l'intérieur de la méthode de la classe anon, l'élément simple est défini, puis ce 'résultat' extrait une fois la méthode est terminée. VALIDE, mais code laid.

1
répondu Robin 2009-04-03 18:24:35

classes anonymes:

  • ne peut avoir quoi que ce soit static dans la définition (classe statique, champ statique, initialiseur statique, etc.)
  • les champs ne peuvent pas être inspectés dans Eclipse
  • ne peut pas être utilisé comme type ( Foo myFoo=new Foo(){int x=0;} ne fonctionne pas)
  • ne peut pas être localisé en utilisant le nom de classe dans Eclipse (la recherche de Foo ne fonctionne pas pour moi)
  • ne peut pas être réutilisé

les classes anonymes peuvent cependant avoir un initialiseur comme {super.foo(finalVariable+this.bar);}

classes intérieures nommées n'ont pas ces limites, mais même si on est utilisé exclusivement au milieu d'une longue procédure, la déclaration devra être déplacée à la classe suivante nommée.

je préfère personnellement les classes intérieures anonymes si les restrictions ne s'appliquent pas parce que:

  • je sais supplémentaires les champs ne sont référencés dans la définition de classe.
  • Eclipse peut les convertir en classes imbriquées facilement.
  • Je n'ai pas besoin de copier les variables que je veux utiliser. Je peux les déclarer finales et les renvoyer. C'est particulièrement utile quand j'ai beaucoup de paramètres.
  • le code qui interagit est proche l'un de l'autre.
1
répondu yingted 2012-05-26 21:12:04

je pense que ce que vous avez fait est parfaitement sensé dans ce cas et de toute façon vous le regardez, je pense que vous êtes vraiment couper les cheveux avec ce problème particulier. Ils sont tous les deux si similaires et l'un ou l'autre fonctionne.

0
répondu Mike Pone 2009-04-03 16:11:38

je pense que c'est une question de goût. Je préfère utiliser des classes anonymes pour Functors . Mais dans votre cas, j'utiliserais une classe interne, car je pense que vous aurez plus que quelques lignes de code là-dedans, peut-être plus qu'une méthode. Et cela soulignerait le fait qu'il ajoute de la fonctionnalité à la superclasse, en la mettant à l'intérieur de la classe, plutôt que caché quelque part dans une méthode. De plus, qui sait, peut-être qu'un jour vous aurez besoin de la sous-classe où. Cela, bien sûr, dépend de ce que vous savez sur la façon dont votre logiciel évoluera. Autre que cela, il suffit de retourner une pièce de monnaie. :)

0
répondu Andrei Vajna II 2009-04-03 16:24:28

vient D'avoir cette discussion aujourd'hui avec mon collègue et fouillait autour de l'opinion populaire.

je suis d'accord avec TofuBeer. Si votre code a plus de 2 lignes, il n'est probablement pas unique et pourrait être réutilisé un jour. Si vous créez un formulaire en utilisant un modèle MVC, vous pourriez avoir 20 éléments contrôlables sur une page au lieu d'encombrer la vue avec des tonnes de classes anonymouse (enfer votre vue a probablement été créée en utilisant un constructeur GUI et le code était auto-genned rendant l'édition de la source même pas une option) vous serez probablement alimenter chaque élément à un contrôleur. Vous pouvez imbriquer des classes internes dans le controller pour gérer chaque interface handler/listener différente que votre vue nécessite. Cela organise très bien le code, surtout si vous avez une convention que votre classe de handler doit être nommée en utilisant le nom de l'élément GUI (comme backButtonHandler pour un backButtonElement). Cela a vraiment bien travaillé pour nous, et nous avons écrit un enregistrement automatique de l'outil (lorsque vous enregistrez un controller sur une vue, la vue Recherche Les classes internes en utilisant le nom de l'élément et les utilise pour un handler sur chaque élément nommé). Cela ne serait pas possible avec des classes anonymes et rend le contrôleur beaucoup plus recyclable.

TLDR: en cas de doute, écrivez un nom de classe intérieure. Vous ne saurez jamais si quelqu'un veut RÉUTILISER votre code un jour (à moins que ce ne soit 2 lignes, alors vous devez vous demander " Est-ce que ce code sent?'). Code qui est bien organisé a beaucoup avantages plus élevés à long terme, surtout lorsque votre projet est en cours d'entretien.

0
répondu dolbysurnd 2013-04-16 22:23:40

avec des classes intérieures anonymes, nous ne pouvons pas changer l'état des membres de classe inclus. Ils doivent être déclarés définitifs.

0
répondu ramakrishna narla 2016-02-27 12:18:12