Pregunta

¿Cuáles son las buenas razones para prohibir la herencia en Java, por ejemplo, mediante el uso de clases finales o clases utilizando un único constructor privado sin parámetros? ¿Cuáles son las buenas razones para hacer un método final?

¿Fue útil?

Solución

Su mejor referencia aquí es el Artículo 19 del excelente libro "Eficaz Java" de Joshua Bloch, llamado "Diseño y documento para herencia o, de lo contrario, lo prohíbe". (Es el ítem 17 en la segunda edición y el ítem 15 en la primera edición). Realmente deberías leerlo, pero lo resumiré.

La interacción de las clases heredadas con sus padres puede ser sorprendente e impredecible si el antepasado no fue diseñado para ser heredado.

Por lo tanto, las clases deben venir en dos tipos:

  1. Clases diseñadas para ser extendidas , y con suficiente documentación para describir cómo se debe hacer

  2. Clases marcadas final

Si está escribiendo código puramente interno, esto puede ser un poco excesivo. Sin embargo, el esfuerzo adicional que implica agregar cinco caracteres a un archivo de clase es muy pequeño. Si escribe solo para el consumo interno, un codificador futuro siempre puede eliminar el 'final'; puede considerarlo como una advertencia que dice "esta clase no se diseñó teniendo en cuenta la herencia".

Otros consejos

Es posible que desee hacer que un método sea definitivo para que las clases superiores no puedan cambiar el comportamiento con el que se cuenta en otros métodos. Los métodos a los que se llama en constructores a menudo se declaran definitivos para que no tenga sorpresas desagradables al crear objetos.

Una razón para hacer una final de clase sería si quisieras forzar la composición sobre la herencia. Esto es generalmente deseable para evitar el acoplamiento estrecho entre clases.

Hay 3 casos de uso en los que puedes ir a los métodos finales.

  1. Para evitar que la clase derivada anule una funcionalidad de clase base en particular.
  2. Esto es para fines de seguridad, donde la clase base proporciona algunas funciones centrales importantes del marco donde se supone que la clase derivada no debe cambiarlo.
  3. Los métodos finales son más rápidos que los métodos de instancia, ya que no se utiliza el concepto de tabla virtual para los métodos finales y privados. Entonces, siempre que haya una posibilidad, intente usar métodos finales.

Propósito para hacer una final de clase:

Para que nadie pueda extender esas clases y cambiar su comportamiento.

Por ejemplo: clase envoltura Integer es una clase final. Si esa clase no es definitiva, cualquiera puede extender Integer a su propia clase y cambiar el comportamiento básico de la clase entera. Para evitar esto, Java creó todas las clases de envoltura como clases finales.

es posible que desee crear objetos inmutables ( http://en.wikipedia.org/wiki/Immutable_object ), es posible que desee crear un singleton ( http://en.wikipedia.org/wiki/ Singleton_pattern ), o quizás desee evitar que alguien anule el método por razones de eficiencia, seguridad o seguridad.

La herencia es como una motosierra: muy poderosa, pero horrible en las manos equivocadas. O bien, diseña una clase para heredarla (lo que puede limitar la flexibilidad y tomar mucho más tiempo) o debería prohibirla.

Consulte los artículos 16 y 17 de Effective Java 2nd edition, o la publicación de mi blog " ; Impuesto sobre sucesiones " .

Hmmm ... puedo pensar en dos cosas:

Es posible que tenga una clase que se ocupe de ciertos problemas de seguridad. Subclasificando y alimentando a su sistema la versión subclasificada de él, un atacante puede eludir las restricciones de seguridad. P.ej. su aplicación podría admitir complementos y, si un complemento puede subclasificar sus clases relevantes para la seguridad, puede usar este truco para contrabandear de alguna manera una versión subclasificada de la misma en su lugar. Sin embargo, esto es algo con lo que Sun tiene que lidiar con respecto a los applets y similares, tal vez no sea un caso tan realista.

Una mucho más realista es evitar que un objeto se vuelva mutable. P.ej. ya que las cadenas son inmutables, su código puede mantener referencias a él con seguridad

 String blah = someOtherString;

en lugar de copiar la cadena primero. Sin embargo, si puede crear una subclase de Cadena, puede agregarle métodos que le permitan modificar el valor de la cadena, ahora ningún código puede confiar en que la cadena se mantendrá igual si solo copia la cadena como se indica anteriormente, en su lugar, debe duplicar la cadena. cadena.

Para evitar que las personas hagan cosas que podrían confundirse a sí mismas y a otras personas. Imagine una biblioteca de física donde tenga algunas constantes o cálculos definidos. Sin usar la palabra clave final, alguien podría venir y redefinir los cálculos básicos o las constantes que NUNCA deberían cambiar.

Además, si está escribiendo una clase de código cerrado comercial, es posible que no quiera que la gente pueda cambiar la funcionalidad en el futuro, especialmente si necesita dar soporte para ella y la gente ha anulado su método y se queja de que llamarlo da resultados inesperados.

Si marca las clases y los métodos como finales, es posible que note una pequeña ganancia de rendimiento, ya que el tiempo de ejecución no tiene que buscar el método de clase correcto para invocar un objeto determinado. Los métodos no finales se marcan como virtuales para que puedan extenderse adecuadamente si es necesario, los métodos finales se pueden vincular directamente o compilar en línea en la clase.

Desea que el método sea definitivo para que las clases que se superan no cambien su comportamiento. Cuando quiera poder cambiar el comportamiento, haga público el método. Cuando se invalida un método público, se puede cambiar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top