2010-01-30 13 views
9

Entiendo la motivación para hacer métodos individuales de una clase sealed/final, pero ¿para qué sirve prohibir por completo la herencia de la clase? Si bien permitir la anulación de ciertos métodos puede causar que sucedan cosas malas, no veo cómo permitir que la herencia de su clase simplemente le agregue comportamiento sin anular el comportamiento existente podría ser algo malo. Si realmente quiere desautorizar cualquier cosa en su clase, ¿por qué no acaba de hacer que todos los métodos sean definitivos, pero aún así permitir la herencia con el propósito de agregar comportamiento?¿Por qué harías una clase completa sellada/final?

+0

En el caso de java.utilidenseID encuentro frustrante la imposibilidad de crear una subclase. –

Respuesta

3

Un equipo de desarrollo de software/organización podría querer aplicar ciertos estándares de codificación. Por ejemplo, para mejorar la legibilidad, es posible que solo quieran que el atributo X de la clase Y se modifique con el método Z y nada más. Si la clase no fuera final, algún desarrollador podría extender la clase Y y agregar el método W, que podría modificar X de una manera diferente y causar confusión y demora a la hora de comprender el código escrito.

+0

¿No está haciendo el atributo X privado lo mismo? – Dalius

+1

@Dalius Incluso con X private, quizás se desee que solo una llamada directa a Z en un objeto Y afecte X. Si una clase W anula Z, entonces usted puede modificar X mediante una llamada a Z en un objeto W, que rompe el deseo inicial de cambiar X solo a través de una llamada al método Z directamente desde un objeto Y. Personalmente, nunca he visto esa situación, pero supongo que puede suceder. –

4

Hay algunas buenas discusiones acerca de esto en el "¿Por qué cadena es final en Java" pregunta: Why is String class declared final in Java?

El resumen básico en ese caso, es decir, cadena es inmutable, y si pudiera tener subclases, la subclase podría hazlo mutable

2

Piénsalo de esta manera: Pasaste tus últimos 3 meses trabajando en una clase base para tu propio framework que otros van a usar, y toda la coherencia del framework se basa en el código escrito en esta clase, modificando esta clase puede causar fallas, errores y mala conducta en su marco, ¿cómo puede evitar que sus grandes programadores la extiendan y anulen uno de sus métodos?

Además de esto, hay clases que se supone que son inmutables, como la clase java.lang.String en Java, extenderla y cambiar su comportamiento podría ser un gran desastre.

Finalmente, a veces establecer una clase o método como final aumentará el rendimiento, pero nunca lo he probado, y no veo ningún motivo en la tierra para hacer una clase/método final para una ganancia de rendimiento muy pequeña que es igual a cero en comparación con el tiempo necesario para hacer otras cosas en el programa.

+0

1. La pregunta es sobre permitir subclases para agregar comportamiento. Entiendo por qué querría prohibir la anulación. 2. Si una clase te toma 3 meses para escribir, probablemente sea demasiado. – dsimcha

+0

No tome 3 meses literariamente, la idea era una clase importante, en un contexto frágil, y donde cualquier otra clase espera que obedezca un cierto comportamiento. –

3

Más en general, una clase puede hacerse definitiva para preservar las invariantes que la hacen funcionar. Recomiendo encarecidamente la "Java efectiva" de Joshua Bloch para una excelente discusión sobre este y otros temas relacionados.

0

Creo que depende.

Si tengo una aplicación interna, no usaría la versión final en el nivel de clase de forma predeterminada. El código simplemente se llena demasiado. En algunas circunstancias, el modificador final es incluso realmente molesto, si quiero refactorizar de forma segura (consulte el término programming by difference). En algunos casos, la 'manía por defecto' hizo grandes problemas cuando intenté refactorizar.

Por otro lado, si diseño un api/framework donde el código es más extensivo usaría el final para las clases 'más agresivamente'. Aquí la extensión incorrecta puede ser un gran problema y el modificador "final" es una forma segura de evitar tales errores de programación.

Pero me opongo a decir el uso 'final' por defecto como muchos lo hacen. A menudo tiene más inconvenientes como ventajas. Para mí, los valores predeterminados deberían ser "configuración sensible y más común".

0

Por lo que yo sé, se trata de mantener invariantes.

En una situación análoga, por ejemplo, podría dejar sus atributos públicos, pero luego perdería el control sobre sus valores porque los clientes podrían cambiarlos directamente, rompiendo algunas propiedades que desea mantener. Por lo tanto, de la misma manera que prohíbe a los clientes acceder a algunos (la mayoría de los campos) directamente para mantener algún invariante, también hace que su clase/método sea definitiva para mantener invariante al respecto.

Un ejemplo común que veo tiene que ver con la inmutabilidad, que se puede romper si una clase no es definitiva.

El problema no es realmente cuando un usuario extiende una clase y la usa solo en su sistema, viviendo con su propio "desastre" aislado de todo lo demás. El problema real tiene que ver con el hecho de que las clases/métodos/atributos/objetos/... no existen de forma aislada.

Supongamos que tiene una colección de clases CC1 que colabora con algún objetivo, y una de esas clases CC1_A debe "producir" solo objetos inmutables (o cualquier otra invariante que desee). Luego continúe y amplíe CC1_A, haciendo CC2_AX (A extendido en una colección de segunda clase). Lo que puedes hacer ahora es usar cosas CC1 pasando un CC2_AX donde se requiere un CC1_A. Sin embargo, CC1 se construyó suponiendo que los objetos CC1_A son inmutables, pero sus objetos CC2_AX no lo son (supongamos que no son solo por el ejemplo). Esto puede ocasionar serios problemas en su programa. Tal problema puede ocurrir incluso internamente en una clase. Por ejemplo, los métodos de CC1_A probablemente asuman que los objetos CC1_A son inmutables, por lo que los métodos de CC2_AX que provienen de CC1_A pueden fallar porque CC2_AX interrumpe la propiedad de inmutabilidad.

En nuestros sistemas, hoy tenemos muchas clases y mucho de lo que hacemos va implícitamente. Entonces, no siempre pensamos en las invariantes que nos gustaría mantener. Esto no hace las cosas más fáciles.

Por cierto, algunos otros invariantes incluyen cosas como:

  • El método para ordenar debe permanecer estable.
  • El < método > utiliza el < otro algoritmo como >.
  • Este <clase> La implementación de la lista debe usar simplemente la implementación de la lista vinculada como se describe < en algún lugar >.

Sigue y sigue. Algunas clases son útiles solo porque mantienen invariantes más fuertes (por ejemplo, el uso de un algoritmo en particular), y la extensión permite a las personas romper fácilmente ese tipo de cosas. Y una razón por la cual todo esto es un problema tiene que ver con que estas cosas no viven aisladas.

Cuestiones relacionadas