En Java, la anulación es una característica que permite que una subclase o clase secundaria proporcione una implementación específica de un método que ya proporciona una de sus superclases o clases principales. Cuando un método en una subclase tiene el mismo nombre, los mismos parámetros o firma y el mismo tipo de retorno (o subtipo) que un método en su superclase, entonces se dice que el método en la subclase anular el método en la superclase.
La anulación de métodos es una de las formas en que Java logra Polimorfismo en tiempo de ejecución . La versión de un método que se ejecuta estará determinada por el objeto que se utilice para invocarlo. Si se usa un objeto de una clase principal para invocar el método, entonces se ejecutará la versión de la clase principal, pero si se usa un objeto de la subclase para invocar el método, entonces se ejecutará la versión de la clase secundaria. En otras palabras, es el tipo de objeto al que se hace referencia (no el tipo de variable de referencia) que determina qué versión de un método anulado se ejecutará.
Ejemplo de anulación de métodos en Java
A continuación se muestra la implementación de la anulación del método Java:
Java
// Java program to demonstrate> // method overriding in java> // Base Class> class> Parent {> >void> show() { System.out.println(>'Parent's show()'>); }> }> // Inherited class> class> Child>extends> Parent {> >// This method overrides show() of Parent> >@Override> void> show()> >{> >System.out.println(>'Child's show()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >// If a Parent type reference refers> >// to a Parent object, then Parent's> >// show is called> >Parent obj1 =>new> Parent();> >obj1.show();> >// If a Parent type reference refers> >// to a Child object Child's show()> >// is called. This is called RUN TIME> >// POLYMORPHISM.> >Parent obj2 =>new> Child();> >obj2.show();> >}> }> |
>
>Producción
Parent's show() Child's show()>
Reglas para la anulación de métodos Java
1. Modificadores de acceso y anulación
El modificador de acceso porque un método anulado puede permitir más, pero no menos, acceso que el método anulado. Por ejemplo, un método de instancia protegido en la superclase puede hacerse público, pero no privado, en la subclase. Hacerlo generará un error en tiempo de compilación.
Java
// A Simple Java program to demonstrate> // Overriding and Access-Modifiers> class> Parent {> >// private methods are not overridden> >private> void> m1()> >{> >System.out.println(>'From parent m1()'>);> >}> >protected> void> m2()> >{> >System.out.println(>'From parent m2()'>);> >}> }> class> Child>extends> Parent {> >// new m1() method> >// unique to Child class> >private> void> m1()> >{> >System.out.println(>'From child m1()'>);> >}> >// overriding method> >// with more accessibility> >@Override> public> void> m2()> >{> >System.out.println(>'From child m2()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj1 =>new> Parent();> >obj1.m2();> >Parent obj2 =>new> Child();> >obj2.m2();> >}> }> |
>
generador de números aleatorios java
>Producción
From parent m2() From child m2()>
2. Los métodos finales no se pueden anular.
Si no queremos que se anule un método, lo declaramos como final . Por favor mira Usando Final con herencia .
Java
// A Java program to demonstrate that> // final methods cannot be overridden> class> Parent {> >// Can't be overridden> >final> void> show() {}> }> class> Child>extends> Parent {> >// This would produce error> >void> show() {}> }> |
>
>
Producción
13: error: show() in Child cannot override show() in Parent void show() { } ^ overridden method is final> 3. Los métodos estáticos no se pueden anular (Anulación de método frente a Ocultación de método):
Cuando define un método estático con la misma firma que un método estático en la clase base, se conoce como ocultamiento del método . La siguiente tabla resume lo que sucede cuando define un método con la misma firma que un método en una superclase.
| Método de instancia de superclase | Método estático de superclase | |
|---|---|---|
| Método de instancia de subclase | Anulaciones | Genera un error en tiempo de compilación |
| Método estático de subclase | Genera un error en tiempo de compilación | Se esconde |
Java
// Java program to show that> // if the static method is redefined by> // a derived class, then it is not> // overriding, it is hiding> class> Parent {> >// Static method in base class> >// which will be hidden in subclass> >static> void> m1()> >{> >System.out.println(>'From parent '> >+>'static m1()'>);> >}> >// Non-static method which will> >// be overridden in derived class> >void> m2()> >{> >System.out.println(> >'From parent '> >+>'non - static(instance) m2() '>);> >}> }> class> Child>extends> Parent {> >// This method hides m1() in Parent> >static> void> m1()> >{> >System.out.println(>'From child static m1()'>);> >}> >// This method overrides m2() in Parent> >@Override> public> void> m2()> >{> >System.out.println(> >'From child '> >+>'non - static(instance) m2() '>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj1 =>new> Child();> >// As per overriding rules this> >// should call to class Child static> >// overridden method. Since static> >// method can not be overridden, it> >// calls Parent's m1()> >obj1.m1();> >// Here overriding works> >// and Child's m2() is called> >obj1.m2();> >}> }> |
>
>Producción
From parent static m1() From child non - static(instance) m2()>
4. Los métodos privados no se pueden anular
métodos privados no se pueden anular ya que están vinculados durante el tiempo de compilación. Por lo tanto, ni siquiera podemos anular métodos privados en una subclase. (Ver este para detalles).
Java
class> SuperClass {> >private> void> privateMethod()> >{> >System.out.println(> >'This is a private method in SuperClass'>);> >}> >public> void> publicMethod()> >{> >System.out.println(> >'This is a public method in SuperClass'>);> >privateMethod();> >}> }> class> SubClass>extends> SuperClass {> >// This is a new method with the same name as the> >// private method in SuperClass> >private> void> privateMethod()> >{> >System.out.println(> >'This is a private method in SubClass'>);> >}> >// This method overrides the public method in SuperClass> >public> void> publicMethod()> >{> >System.out.println(> >'This is a public method in SubClass'>);> >privateMethod();>// calls the private method in> >// SubClass, not SuperClass> >}> }> public> class> Test {> >public> static> void> main(String[] args)> >{> >SuperClass obj1 =>new> SuperClass();> >obj1.publicMethod();>// calls the public method in> >// SuperClass> >SubClass obj2 =>new> SubClass();> >obj2.publicMethod();>// calls the overridden public> >// method in SubClass> >}> }> |
preity zinta
>
>Producción
This is a public method in SuperClass This is a private method in SuperClass This is a public method in SubClass This is a private method in SubClass>
5. El método principal debe tener el mismo tipo (o subtipo) de retorno.
Desde Java 5.0 en adelante, es posible tener diferentes tipos de retorno para un método primordial en la clase secundaria, pero el tipo de retorno del hijo debe ser un subtipo del tipo de retorno del padre. Este fenómeno se conoce como el tipo de retorno covariante .
Java
class> SuperClass {> >public> Object method()> >{> >System.out.println(> >'This is the method in SuperClass'>);> >return> new> Object();> >}> }> class> SubClass>extends> SuperClass {> >public> String method()> >{> >System.out.println(> >'This is the method in SubClass'>);> >return> 'Hello, World!'>;> >}> }> public> class> Test {> >public> static> void> main(String[] args)> >{> >SuperClass obj1 =>new> SuperClass();> >obj1.method();> >SubClass obj2 =>new> SubClass();> >obj2.method();> >}> }> |
>
>Producción
This is the method in SuperClass This is the method in SubClass>
6. Invocar un método anulado desde una subclase
Podemos llamar al método de la clase principal en el método principal usando el súper palabra clave .
Java
// A Java program to demonstrate that overridden> // method can be called from sub-class> // Base Class> class> Parent {> >void> show() { System.out.println(>'Parent's show()'>); }> }> // Inherited class> class> Child>extends> Parent {> >// This method overrides show() of Parent> >@Override> void> show()> >{> >super>.show();> >System.out.println(>'Child's show()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj =>new> Child();> >obj.show();> >}> }> |
git agregar todo
>
>Producción
Parent's show() Child's show()>
Anulación y constructor
No podemos anular el constructor ya que la clase principal y la secundaria nunca pueden tener un constructor con el mismo nombre (el nombre del constructor siempre debe ser el mismo que el nombre de la clase).
Anulación y manejo de excepciones
A continuación se presentan dos reglas a tener en cuenta al anular métodos relacionados con el manejo de excepciones.
Regla 1
Si el método anulado de la superclase no genera una excepción, el método anulado de la subclase solo puede generar la excepción no marcada , generar una excepción marcada generará un error en tiempo de compilación.
Java
// Java program to demonstrate overriding when> // superclass method does not declare an exception> class> Parent {> >void> m1() { System.out.println(>'From parent m1()'>); }> >void> m2() { System.out.println(>'From parent m2()'>); }> }> class> Child>extends> Parent {> >@Override> >// no issue while throwing unchecked exception> >void> m1()>throws> ArithmeticException> >{> >System.out.println(>'From child m1()'>);> >}> >@Override> >// compile-time error> >// issue while throwing checked exception> >void> m2()>throws> Exception> >{> >System.out.println(>'From child m2'>);> >}> }> |
>
>
Producción
error: m2() in Child cannot override m2() in Parent void m2() throws Exception{ System.out.println('From child m2');} ^ overridden method does not throw Exception> Regla #2
Si el método anulado de la superclase genera una excepción, el método anulado de la subclase solo puede generar la misma excepción de subclase. Lanzar excepciones de padres en el Jerarquía de excepciones provocará un error en el tiempo de compilación. Además, no hay ningún problema si el método anulado de la subclase no genera ninguna excepción.
Java
// Java program to demonstrate overriding when> // superclass method does declare an exception> class> Parent {> >void> m1()>throws> RuntimeException> >{> >System.out.println(>'From parent m1()'>);> >}> }> class> Child1>extends> Parent {> >@Override> >// no issue while throwing same exception> >void> m1()>throws> RuntimeException> >{> >System.out.println(>'From child1 m1()'>);> >}> }> class> Child2>extends> Parent {> >@Override> >// no issue while throwing subclass exception> >void> m1()>throws> ArithmeticException> >{> >System.out.println(>'From child2 m1()'>);> >}> }> class> Child3>extends> Parent {> >@Override> >// no issue while not throwing any exception> >void> m1()> >{> >System.out.println(>'From child3 m1()'>);> >}> }> class> Child4>extends> Parent {> >@Override> >// compile-time error> >// issue while throwing parent exception> >void> m1()>throws> Exception> >{> >System.out.println(>'From child4 m1()'>);> >}> }> |
>
>
Producción
error: m1() in Child4 cannot override m1() in Parent void m1() throws Exception ^ overridden method does not throw Exception>
Método primordial y abstracto
Los métodos abstractos en una interfaz o clase abstracta deben anularse en clases concretas derivadas, de lo contrario, se generará un error en tiempo de compilación.
Método anulado y sincronizado/estrictofp
La presencia de un modificador sincronizado/strictfp con el método no tiene efecto en las reglas de anulación, es decir, es posible que un método sincronizado/strictfp pueda anular uno no sincronizado/strictfp y viceversa.
Nota:
convertir cadena a int
- En C++ necesitamos palabra clave virtual para lograr anulación o Polimorfismo en tiempo de ejecución . En Java, los métodos son virtuales por defecto.
- Podemos tener anulación de métodos multinivel.
Java
// A Java program to demonstrate> // multi-level overriding> // Base Class> class> Parent {> >void> show() { System.out.println(>'Parent's show()'>); }> }> // Inherited class> class> Child>extends> Parent {> >// This method overrides show() of Parent> >void> show() { System.out.println(>'Child's show()'>); }> }> // Inherited class> class> GrandChild>extends> Child {> >// This method overrides show() of Parent> >void> show()> >{> >System.out.println(>'GrandChild's show()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj1 =>new> GrandChild();> >obj1.show();> >}> }> |
>
>Producción
GrandChild's show()>
Anulación de métodos frente a sobrecarga de métodos
1. Sobrecarga Se trata del mismo método con diferentes firmas. La anulación se trata del mismo método y la misma firma, pero diferentes clases conectadas mediante herencia.
2. La sobrecarga es un ejemplo de polimorfismo en tiempo de compilación y la anulación es un ejemplo de tiempo de ejecución. polimorfismo .
Preguntas frecuentes sobre la anulación de métodos Java
P1. ¿Qué es la anulación de métodos?
Como se indicó anteriormente, los métodos anulados permiten que Java admita polimorfismo en tiempo de ejecución . El polimorfismo es esencial para la programación orientada a objetos por una razón: permite que una clase general especifique métodos que serán comunes a todos sus derivados y al mismo tiempo permite que las subclases definan la implementación específica de algunos o todos esos métodos. Los métodos anulados son otra forma en que Java implementa el aspecto del polimorfismo de una interfaz y múltiples métodos. Envío de método dinámico Es uno de los mecanismos más poderosos que el diseño orientado a objetos aporta a la reutilización y la solidez del código. La capacidad de existir bibliotecas de código para llamar a métodos en instancias de nuevas clases sin recompilar y al mismo tiempo mantener una interfaz abstracta limpia es una herramienta profundamente poderosa. Los métodos anulados nos permiten llamar a métodos de cualquiera de las clases derivadas sin siquiera conocer el tipo de objeto de clase derivada.
P2. ¿Cuándo aplicar la anulación de métodos? (con ejemplo)
Anulación y Herencia : Parte de la clave para aplicar con éxito el polimorfismo es comprender que las superclases y subclases forman una jerarquía que va de menor a mayor especialización. Si se usa correctamente, la superclase proporciona todos los elementos que una subclase puede usar directamente. También define aquellos métodos que la clase derivada debe implementar por sí sola. Esto permite a la subclase la flexibilidad de definir sus métodos, y aún así impone una interfaz consistente. Así, al combinar la herencia con métodos anulados, una superclase puede definir la forma general de los métodos que serán utilizados por todas sus subclases. Veamos un ejemplo más práctico que utiliza la anulación de métodos. Considere un software de gestión de empleados para una organización, deje que el código tenga una clase base simple Empleado, y la clase tenga métodos como aumentarSalario(), transferir(), promover(), etc. Diferentes tipos de empleados como Gerente, Ingeniero, ..etc pueden tener sus implementaciones de los métodos presentes en la clase base Empleado. En nuestro software completo, sólo necesitamos pasar una lista de empleados en todas partes y llamar a los métodos apropiados sin siquiera saber el tipo de empleado. Por ejemplo, podemos aumentar fácilmente el salario de todos los empleados recorriendo la lista de empleados. Cada tipo de empleado puede tener su lógica en su clase, no debemos preocuparnos porque si riseSalary() está presente para un tipo de empleado específico, solo se llamará a ese método.
Java
// Java program to demonstrate application>// of overriding in Java>// Base Class>class>Employee {>>public>static>int>base =>10000>;>>int>salary() {>return>base; }>}>// Inherited class>class>Manager>extends>Employee {>>// This method overrides salary() of Parent>>int>salary() {>return>base +>20000>; }>}>// Inherited class>class>Clerk>extends>Employee {>>// This method overrides salary() of Parent>>int>salary() {>return>base +>10000>; }>}>// Driver class>class>Main {>>// This method can be used to print the salary of>>// any type of employee using base class reference>>static>void>printSalary(Employee e)>>{>>System.out.println(e.salary());>>}>>public>static>void>main(String[] args)>>{>>Employee obj1 =>new>Manager();>>// We could also get type of employee using>>// one more overridden method.loke getType()>>System.out.print(>'Manager's salary : '>);>>printSalary(obj1);>>Employee obj2 =>new>Clerk();>>System.out.print(>'Clerk's salary : '>);>>printSalary(obj2);>>}>}>>>ProducciónManager's salary : 30000 Clerk's salary : 20000>
Artículo relacionado
- Envío de métodos dinámicos o polimorfismo en tiempo de ejecución en Java
- Anulando el método igual () de la clase Objeto
- Anulando el método toString() de la clase Object
- Sobrecarga en java
- Salida del programa Java | Conjunto 18 (anulación)