Se dice que un método en una subclase anula un método en su superclase si ese método tiene una firma idéntica a un método en su superclase. Cuando un objeto de la subclase llama a este método, siempre se llamará a la versión Overridden. En otras palabras, el método que se anuló en la superclase se ocultará.
La JVM tiene 2 opciones, puede llamar al método original presente en la superclase o al método Overridden presente en la subclase. Debido al enlace tardío, esta decisión se toma en tiempo de ejecución y no en tiempo de compilación.
¿Podemos anular un método final?
No, los Métodos que se declaran como definitivos no se pueden Anular ni ocultar. Por esta misma razón, un método debe declararse como final solo cuando estamos seguros de que está completo.
- Cabe señalar que los métodos abstractos no se pueden declarar como finales porque no están completos y es necesario anularlos.
- Los métodos se declaran finales en Java para evitar que las subclases los anulen y cambien su comportamiento, la razón por la que esto funciona se analiza al final de este artículo.
- La ventaja de la palabra clave final es que evita que los desarrolladores cambien, de forma intencionada o no, el comportamiento de los métodos que no deberían cambiarse por motivos de seguridad u otros.
Resultado de anular un método final
En el siguiente código:
- La clase IntegralOperations tiene dos métodos, suma y resta que realizan la operación esperada.
- Tanto la suma como la resta se declaran definitivas.
- El hijo de la clase extiende IntegralOperations e intenta Anular sumas y restas.
Java
// Java Program to demonstrate result of overriding a final // method class IntegralOperations { // add declared as final final int add(int a, int b) { return a + b; } // subtract declared as final final int subtract(int a, int b) { return a - b; } } class child extends IntegralOperations { // try to override add @Override int add(int a, int b) { return a - b; } // try to override subtract @Override int subtract(int a, int b) { return a * b; } } public class Main { public static void main(String[] args) { child c1 = new child(); System.out.println(c1.add(1, 4)); } }
Producción
prog.java:13: error: add(int,int) in child cannot override add(int,int) in IntegralOperations @Override int add(int a, int b) { return a - b; } ^ overridden method is final prog.java:16: error: subtract(int,int) in child cannot override subtract(int,int) in IntegralOperations @Override int subtract(int a, int b) { return a * b; } ^ overridden method is final 2 errors
Como es evidente en el resultado anterior, intentar anular un método final provoca un error en tiempo de compilación.
Esto prueba que los métodos finales no se pueden anular en Java.
¿Por qué la palabra clave final evita la anulación?
Al principio, se discutió que los métodos que se anulan siguen el envío de métodos dinámicos (enlace tardío), pero los métodos que se declaran como finales siguen el enlace estático (enlace temprano), lo que significa que la definición del método se agrupará con un cuerpo en compilación -el tiempo mismo.
En otras palabras, JVM debe saber exactamente qué método llamar en tiempo de compilación. Para lograr esto, para cada definición de método final debe haber un cuerpo único. Pero si se permite la anulación, puede haber varios cuerpos para una definición de método y el compilador no podrá elegir uno de ellos.
Este problema se ve en el ejemplo anterior donde tenemos dos cuerpos cada uno para métodos de suma y resta. Esto hace que el compilador arroje un error en tiempo de compilación. De esta forma, la palabra clave final evita la anulación y protege la semántica de un método.