2009-04-03 44 views
40

Tengo una clase, llamémosla LineGraph, que representa un gráfico de líneas. Necesito subclasificarlo, pero la clase derivada solo se usa en un lugar y se acopla a la clase que lo usa. Entonces estoy usando una clase interna.Clases internas anónimas vs nombradas? - ¿mejores prácticas?

Veo dos maneras de hacer esto:

Anónimo clase interna

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

Named clase interna

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

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

No soy un fan de las clases internas anónimas, porque, francamente, creo que se ve muy feo. Pero en el caso de una subclase que solo se usa en un solo lugar, ¿existe un nombre excesivo de clase interna? ¿Cuál es la práctica aceptada?

+5

Lambda's anyone :) – Matt

Respuesta

9

¿Por qué es necesario crear una subclase? Si es solo para anular un método virtual existente, creo que una clase interna anónima está bien. Si está agregando funcionalidad extra, usaría una clase con nombre. Sin embargo, lo convertiría en una clase anidada (es decir, con el modificador static) - Me parece más fácil razonar :)

+0

Mi ejemplo fue algo simplificado. En el código real, anula 5 métodos (no abstractos). –

+0

Eso parece suficiente para que valga la pena convertirlo en una clase con nombre. Me gusta que mis clases anónimas sean pequeñas. –

+1

de acuerdo. Generalmente solo uso clases anónimas si son realmente simples. Más de una definición de función pequeña y la convertiré en una clase interna normal (estática si es posible). Simplemente es más fácil de leer de esa manera. – Herms

0

Creo que lo que has hecho tiene mucho sentido en este caso y en cualquier caso lo miras , Creo que realmente estás dividiendo los pelos con este problema en particular. Ambos son muy similares y cualquiera de ellos funcionará.

+0

Hay muchas ocasiones en las que dos opciones funcionarán pero una es más legible y mantenible que otra. Creo que tiene mucho sentido pedir las opiniones de otras personas cuando tienen dudas sobre cuál es la mejor manera de hacerlo. –

47

Una de las ventajas de las clases internas anónimas es que nadie puede usarla en ningún otro lado, mientras que una clase interna con nombre puede ser utilizada (aunque solo sea por la clase que la creó si se hace privada). Es una pequeña distinción, pero significa que puedes proteger una clase interna para que no sea utilizada accidentalmente en otro lugar.

Además, usar la clase interna anónima le da a cualquiera que lea su código una cabeza arriba: "esta clase se está utilizando solo aquí y en ninguna otra parte". Si ve una clase interna con nombre, alguien podría pensar que se usaría en varios lugares de la clase.

Son muy similares, por lo que ninguno de los dos puntos cambia las reglas del juego. Creo que ayuda a la claridad si utiliza clases internas anónimas para las clases únicas y las clases internas con nombre cuando se usa varias veces dentro de la clase.

+3

+1 Buenos puntos, pero recuerde que las clases también pueden definirse dentro de las funciones. Esto limita su alcance y puede ser una buena pista de que tienen un uso muy localizado. –

+3

Estas son muy buenas razones para no usar clases anónimas. :) –

0

Creo que esto es una cuestión de gusto. Prefiero usar clases anónimas para Functors. Pero en tu caso, usaría una clase interna, ya que creo que estarás empacando más que unas pocas líneas de código, tal vez más que solo un método. Y enfatizaría el hecho de que está agregando funcionalidad a la superclase, poniéndola dentro de la clase, en lugar de estar escondida en algún lugar de un método. Además, quién sabe, tal vez algún día necesites la subclase else en donde. Esto, por supuesto, depende de cuánto sabe acerca de cómo evolucionará su software. Aparte de eso, solo tira una moneda. :)

4

Las clases internas anónimas son difíciles de depurar en Eclipse (eso es lo que uso). No podrá mirar los valores de variables/valores de inyección simplemente haciendo clic derecho.

2

Clases internas anónimas generalmente serían el camino a seguir. Los encuentro muy legibles Sin embargo, si la instancia de esa clase alguna vez necesita ser serializada (aunque sea solo porque es un campo de otra cosa), recomendaría encarecidamente el uso de clases internas con nombre. Los nombres de las clases internas anónimas en bytecode pueden cambiar muy fácilmente, y esto puede romper la serialización.

36

(contador de puntos a Daniel Lew)

Una desventaja de las clases internas anónimas es que nadie puede utilizarlo en cualquier otro lugar, mientras que una clase interna llamada se puede utilizar (aunque sólo sea por la clase que lo creó, si hecho en privado). Es una pequeña distinción, pero significa que puede ayudar a garantizar que una clase interna no se recree accidentalmente en ningún otro lugar.

Además, usar la clase interna anónima le da a cualquiera que lea su código un tiempo más difícil ya que luego tiene que analizar esta clase que surgió de la nada. Usando una clase interna con nombre, puedes organizar más la fuente.

He visto casos en los que hay dos (o más) clases internas anónimas con exactamente el mismo código. En las GUI especialmente (donde puede tener múltiples controles que realizan la misma acción), esto puede aparecer (y estoy hablando de código de producción, no de código que mis alumnos han escrito).

El problema de legibilidad es en ambos sentidos, algunas personas consideran que las clases internas anónimas son mejores, ya que le permiten ver lo que está sucediendo en un lugar, otras lo encuentran como una distracción. Esa parte se reduce a preferencia personal.

También hacer una clase estática es más eficiente, si declaras una clase interna anónima en una instancia, habrá más sobrecarga, lo cual, si no necesitas acceder a las variables de instancia, es un desperdicio (pero probablemente no vale la pena preocuparse hasta que se presente como un problema).

Mi preferencia personal es utilizar clases no anónimas, ya que permiten una mayor flexibilidad cuando el código se modifica más tarde.

+3

Esto es lo que encuentro feo acerca de las clases internas anónimas. Estás leyendo el código, y de repente aparece esta definición de clase en el medio de un grupo de campos. –

+0

Siempre tengo problemas para alinear el código dentro de la clase anónima. No importa cuánto lo intente, el código todavía se ve feo: D – janetsmith

+0

Estoy de acuerdo: encuentro que el código es difícil de leer/depurar si hay muchas clases internas anónimas. En lugar de declarar clases internas anónimas dentro de múltiples funciones (YUCK!), Encuentro que es una práctica mucho mejor dedicar secciones del archivo a clases internas con nombre, es decir, la parte inferior del archivo. –

3

Una desventaja de las clases internas es que no pueden ser estáticas. Esto significa que mantendrá una referencia a la clase externa que los contiene.

Las clases internas no estáticas pueden ser un problema. Por ejemplo, recientemente tuvimos una clase interna siendo serializada, pero la clase externa no era serializable. La referencia oculta significaba que la clase externa también se serializaría, lo que por supuesto fracasó, pero llevó un tiempo descubrir por qué.

Donde trabajo, se recomiendan las clases internas estáticas en nuestras mejores prácticas de codificación (cuando sea posible) ya que llevan menos equipaje oculto y son más delgadas.

1

No tengo ningún problema con las clases anónimas simples. Pero si consta de más de unas pocas líneas de código o un par de métodos, una clase interna es más clara. También creo que bajo ciertas condiciones nunca deberían usarse. Como cuando deben devolver datos.

He visto un código donde se utiliza una matriz final de 1 elemento para pasar datos de una llamada a una clase interna anónima. Dentro del método de la clase anon, el elemento individual se establece, luego este 'resultado' se extrae una vez que se completa el método. Código válido pero feo

7

Do the simplest thing that could possibly work: Usa la clase interna anónima.

Si más adelante descubre que necesita un ámbito más amplio, vuelva a configurar el código para admitir esto.

(Usted podría hacer lo mismo con las variables - ponerlos en el ámbito más específico Tiene sentido hacer lo mismo con otros activos de origen..)

3

Mi regla personal de oro: Si la clase interna anónima va a ser pequeño, seguir con una clase anónima. Pequeño se define como alrededor de 20 - 30 líneas o menos. Si va a ser más largo, comienza a ser ilegible en mi opinión, así que lo hago una clase interna con nombre. Recuerdo que una vez vi una clase interna anónima de más de 4000 líneas.

2

Las clases anónimas no pueden tener un constructor, ya que no tienen un nombre. Si necesita pasar otras variables distintas a las de los constructores de la clase que está extendiendo, debe usar una clase interna con nombre (estática). Esto a veces puede superarse usando variables finales en el método/código circundante, pero es un poco feo (y puede llevar a lo que Robin dijo).

clases
1

Anónimo:

  • no puede tener nada static en la definición (clase estática, campo estático, inicializador estático, etc.)
  • campos no pueden ser inspeccionados en Eclipse
  • no se puede utilizar como una tipo (Foo$1 myFoo=new Foo$1(){int x=0;} no funciona)
  • no puede ser localizado utilizando el nombre de la clase en Eclipse (la búsqueda de Foo$1 no funciona para mí)
  • ca nnot ser reutilizados

clases anónimas pueden, sin embargo, tienen un inicializador como {super.foo(finalVariable+this.bar);}

Named clases internas no tienen estas limitaciones, pero incluso si se utiliza exclusivamente en el medio de un procedimiento largo, el la declaración tendrá que moverse a la siguiente clase nombrada.

Yo personalmente prefiero las clases internas anónimas si las restricciones no se aplican porque:

  • Sé que todos los campos adicionales solamente se hace referencia en la definición de clase.
  • Eclipse puede convertirlos a clases anidadas fácilmente.
  • No necesito copiar las variables que quiero usar. Puedo declararlos definitivos y hacer referencia a ellos. Esto es especialmente útil cuando tengo muchos parámetros.
  • El código que interactúa está muy cerca.
0

Acabo de tener esta discusión hoy con mi compañero de trabajo y estaba buscando la opinión popular.

Estoy de acuerdo con TofuBeer. Si su código tiene más de 2 líneas, es probable que no se trate de una sola vez y que pueda ser reutilizado algún día. Si está creando un formulario usando un patrón MVC, puede tener 20 elementos controlables en una página en lugar de saturar la vista con toneladas de clases anonymouse (probablemente su vista se creó usando un constructor de GUI y el código fue creado automáticamente) editando la fuente ni siquiera una opción) probablemente alimentará cada elemento a un controlador. Puede anidar las clases internas dentro del controlador para manejar cada interfaz diferente de controlador/escucha que requiera su vista. Esto organiza el código realmente bien, especialmente si tiene una convención de que su clase de manejador debe ser nombrada usando el nombre del elemento GUI (como backButtonHandler para un BackButtonElement). Esto funcionó muy bien para nosotros, y escribimos una herramienta de registro automático (cuando registra un controlador en una vista, la vista busca clases internas usando el nombre del elemento y las utiliza para un controlador en cada elemento nombrado). Esto no sería posible con clases anónimas y hace que el controlador sea mucho más reciclable.

TLDR: cuando tenga dudas, escriba una clase interna con nombre.Nunca sabrá si alguien quiere reutilizar su código algún día (a menos que sean 2 líneas, entonces debe preguntarse "¿huele este código?"). El código que está bien organizado tiene beneficios mucho más altos a largo plazo, especialmente cuando su proyecto está en mantenimiento.

0

Con clases internas anónimas, no podemos cambiar el estado de los miembros de la clase incluidos. Necesitan ser declarados como definitivos.

Cuestiones relacionadas