Anulación en Java

Anulación en Java

Cuando una subclase proporciona una implementación específica para un método que ya está definido en su clase principal, se denomina anulación de método. El método anulado en la subclase debe tener los mismos parámetros de nombre y tipo de retorno que el método de la clase principal.

Reglas para anular métodos

  • Los parámetros de nombre y el tipo de retorno deben coincidir con el método principal.
  • Java elige qué método ejecutar en tiempo de ejecución en función del tipo de objeto real, no solo del tipo de variable de referencia.
  • Los métodos estáticos no se pueden anular.
  • El @Anular anotación detecta errores como errores tipográficos en los nombres de los métodos.
Java
   class   Animal     {          void     move  (){      System  .  out  .  println  (      'Animal is moving.'  );             }      void     eat  (){          System  .  out  .  println  (      'Animal is eating.'  );             }   }   class   Dog     extends     Animal  {          @Override     void     move  (){             // move method from Base class is overriden in this      // method      System  .  out  .  println  (  'Dog is running.'  );      }      void     bark  (){          System  .  out  .  println  (  'Dog is barking.'  );             }   }   public     class   Geeks     {      public     static     void     main  (  String  []     args  )      {      Dog     d     =     new     Dog  ();      d  .  move  ();         d  .  eat  ();         d  .  bark  ();      }   }   

Producción
Dog is running. Animal is eating. Dog is barking.  

Explicación: La clase Animal define funcionalidades básicas como mover() y comer() . La clase Perro hereda de Animal y anula el método move() para proporcionar un comportamiento específico El perro corre. Ambas clases pueden acceder a sus propios métodos. Al crear un objeto Perro, llamar a move() ejecuta el método anulado.

Anulación de métodos en Java

Casos especiales en anulación

1. Llamar al método principal usando super

El súper palabra clave Puede invocar el método de la clase principal desde el método principal.

Java
   class   Parent  {          void     show  (){          System  .  out  .  println  (  'Parent's show()'  );      }   }   class   Child     extends     Parent  {          @Override      void     show  (){          super  .  show  ();      System  .  out  .  println  (  'Child's show()'  );      }   }   public     class   Main  {          public     static     void     main  (  String  []     args  ){          Parent     obj     =     new     Child  ();      obj  .  show  ();      }   }   

Producción
Parent's show() Child's show()  

2.  Los métodos finales no se pueden anular

Si no queremos que se anule un método, lo declaramos como  final . por favor vea  Usando Final con herencia

Java
   class   Parent  {          // Can't be overridden      final     void     show  (){          }   }   class   Child     extends     Parent  {          // This would produce error      void     show  ()     {}   }   


Producción :

Método Anulación

3. Métodos estáticos

  • Los métodos estáticos no se pueden anular; definir un método estático en una subclase con la misma firma que en la superclase oculta el método de la superclase.
  • Los métodos de instancia se pueden anular, pero una subclase no puede anular un método estático de superclase.
  • Un método estático en una subclase con la misma firma que un método estático de superclase oculta el método original.
Java
   class   Parent  {      static     void     staticMethod  (){          System  .  out  .  println  (  'Parent static method'  );      }      void     instanceMethod  (){          System  .  out  .  println  (  'Parent instance method'  );      }   }   class   Child     extends     Parent  {          static     void     staticMethod  (){          // Hides Parent's static method      System  .  out  .  println  (  'Child static method'  );      }      @Override      void     instanceMethod  (){             // Overrides Parent's instance method      System  .  out  .  println  (  'Child instance method'  );      }   }   public     class   GFG  {          public     static     void     main  (  String  []     args  ){          Parent     p     =     new     Child  ();          // Calls Parent's static method (hiding)      p  .  staticMethod  ();          // Calls Child's overridden instance method      p  .  instanceMethod  ();         }   }   

Producción
Parent static method Child instance method  

4. Métodos privados

  • Los métodos privados no se pueden anular porque no son visibles para las subclases.
  • Un método de subclase con el mismo nombre se trata como un nuevo método independiente no relacionado con la clase principal.
Java
   class   Parent  {          private     void     display  (){          System  .  out  .  println  (  'Parent private method'  );      }   }   class   Child     extends     Parent  {          void     display  (){          // This is a new method not overriding      System  .  out  .  println  (  'Child method'  );      }   }   public     class   GFG  {          public     static     void     main  (  String  []     args  ){          Child     c     =     new     Child  ();          // Calls Child's method      c  .  display  ();         }   }   

Producción
Child method  

5. Tipos de retorno covariantes

  • En la anulación de métodos, el tipo de retorno del método anulado puede ser una subclase del tipo de retorno del método anulado.
  • Esta característica se conoce como tipo de retorno covariante y permite tipos de retorno más específicos en la subclase.
Java
   class   Parent  {          Parent     getObject  (){          System  .  out  .  println  (  'Parent object'  );      return     new     Parent  ();      }   }   class   Child     extends     Parent  {          @Override          // Covariant return type      Child     getObject  ()     {         System  .  out  .  println  (  'Child object'  );      return     new     Child  ();      }   }   public     class   GFG  {          public     static     void     main  (  String  []     args  ){          Parent     obj     =     new     Child  ();          // Calls Child's method      obj  .  getObject  ();             }   }   

Producción
Child object  

Manejo de excepciones en anulación

  • El método predominante no puede generar excepciones comprobadas nuevas o más amplias que el método de la superclase.
  • Puede generar menos excepciones marcadas o más limitadas.
  • Puede generar excepciones no comprobadas (como RuntimeException) independientemente del método de superclase.
Java
   import     java.io.IOException  ;   class   Parent     {      void     display  ()     throws     IOException     {      System  .  out  .  println  (  'Parent method'  );      }   }   class   Child     extends     Parent     {      @Override      void     display  ()     throws     IOException     {      System  .  out  .  println  (  'Child method'  );      }   }   public     class   GFG  {          public     static     void     main  (  String  []     args  ){          // Parent reference Child object      Parent     obj     =     new     Child  ();         try  {          // Calls Child's overridden method      obj  .  display  ();         }     catch     (  IOException     e  ){          System  .  out  .  println  (  'Exception caught: '     +     e  .  getMessage  ());      }      }   }   

Producción
Child method  

¿Por qué utilizamos la anulación de métodos?

  • Cambiar o mejorar el comportamiento de un método existente en una subclase.
  • Para lograr polimorfismo en tiempo de ejecución, las llamadas a métodos dependen del tipo de objeto real.
  • Reutilizar nombres de métodos reduciendo lógicamente la redundancia.

Ejemplo de la vida real: sistema de gestión de empleados

Entendamos la anulación con una analogía del mundo real.

Imagine el sistema de gestión de empleados de una organización. Todos los empleados comparten algunos comportamientos como aumentarSalario() y promover() pero la lógica difiere para diferentes roles como Gerente o Ingeniero. Podemos crear una única matriz de empleados donde los empleados individuales sean de diferentes tipos (técnicos de ventas, etc.) y llamar a sus funciones. Esto simplifica mucho el código general.

Java
   abstract     class   Employee     {      abstract     void     raiseSalary  ();      abstract     void     promote  ();   }   class   Manager     extends     Employee  {      @Override     void     raiseSalary  (){          System  .  out  .  println  (      'Manager salary raised with incentives.'  );      }      @Override     void     promote  (){          System  .  out  .  println  (      'Manager promoted to Senior Manager.'  );      }   }   class   Engineer     extends     Employee  {          @Override     void     raiseSalary  (){          System  .  out  .  println  (      'Engineer salary raised with bonus.'  );      }      @Override     void     promote  (){          System  .  out  .  println  (      'Engineer promoted to Senior Engineer.'  );      }   }   public     class   Company  {          public     static     void     main  (  String  []     args  ){          Employee  []     employees      =     {     new     Manager  ()     new     Engineer  ()     };      System  .  out  .  println  (  '--- Raising Salaries ---'  );      for     (  Employee     e     :     employees  ){          e  .  raiseSalary  ();         }      System  .  out  .  println  (  'n--- Promotions ---'  );      for     (  Employee     e     :     employees  )     {      e  .  promote  ();      }      }   }   

Producción
--- Raising Salaries --- Manager salary raised with incentives. Engineer salary raised with bonus. --- Promotions --- Manager promoted to Senior Manager. Engineer promoted to Senior Engineer.  

Explicación: Aunque se hace referencia a los objetos Manager e Engineer utilizando el tipo Empleado, Java llama a los métodos anulados de los objetos reales en tiempo de ejecución, lo que demuestra el envío de métodos dinámicos (polimorfismo en tiempo de ejecución).

Artículo relacionado: Sobrecarga de métodos y anulación de métodos