Przesłanianie w Javie

Przesłanianie w Javie

Kiedy podklasa zapewnia specyficzną implementację metody, która jest już zdefiniowana w jej klasie nadrzędnej, nazywa się to przesłonięciem metody. Przesłonięta metoda w podklasie musi mieć takie same parametry nazwy i typ zwracany jak metoda w klasie nadrzędnej.

Zasady zastępowania metod

  • Parametry nazwy i typ zwracany muszą odpowiadać metodzie nadrzędnej.
  • Java wybiera metodę do uruchomienia w czasie wykonywania na podstawie rzeczywistego typu obiektu, a nie tylko typu zmiennej referencyjnej.
  • Metod statycznych nie można zastąpić.
  • The Adnotacja @Zastąp wyłapuje błędy, takie jak literówki w nazwach metod.
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  ();      }   }   

Wyjście
Dog is running. Animal is eating. Dog is barking.  

Wyjaśnienie: Klasa Animal definiuje podstawowe funkcjonalności, takie jak przenosić() I jeść() . Klasa Dog dziedziczy po Animal i zastępuje metoda move() zapewniająca określone zachowanie Pies biega. Obie klasy mogą uzyskać dostęp do własnych metod. Podczas tworzenia obiektu Dog wywołanie funkcji move() powoduje wykonanie przesłoniętej metody.

Przesłonięcie metody w Javie

Specjalne przypadki w zastępowaniu

1. Wywołanie metody nadrzędnej przy użyciu super

The super słowo kluczowe może wywołać metodę klasy nadrzędnej z metody przesłaniającej.

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  ();      }   }   

Wyjście
Parent's show() Child's show()  

2.  Metod końcowych nie można zastąpić

Jeśli nie chcemy, aby metoda została zastąpiona, deklarujemy ją jako  finał . Proszę zobaczyć  Używanie wersji finalnej z dziedziczeniem

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


Wyjście :

MetodaZastępowanie

3. Metody statyczne

  • Metod statycznych nie można zastąpić; zdefiniowanie metody statycznej w podklasie z taką samą sygnaturą jak w nadklasie ukrywa metodę nadklasy.
  • Metody instancji można przesłonić, ale podklasa nie może przesłonić metody statycznej nadklasy.
  • Metoda statyczna w podklasie z tym samym podpisem co metoda statyczna nadklasy ukrywa oryginalną metodę.
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  ();         }   }   

Wyjście
Parent static method Child instance method  

4. Metody prywatne

  • Metod prywatnych nie można zastąpić, ponieważ nie są one widoczne dla podklas.
  • Metoda podklasy o tej samej nazwie jest traktowana jako nowa niezależna metoda niezwiązana z klasą nadrzędną.
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  ();         }   }   

Wyjście
Child method  

5. Kowariantne typy zwrotów

  • W metodzie przesłaniającej typ zwracany przez metodę przesłaniającą może być podklasą typu zwracanego przez metodę zastępowaną.
  • Ta funkcja jest nazywana kowariantnym typem zwracanym i umożliwia bardziej szczegółowe typy zwracanych wartości w podklasie.
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  ();             }   }   

Wyjście
Child object  

Obsługa wyjątków w zastępowaniu

  • Metoda przesłaniająca nie może generować nowych ani szerszych sprawdzonych wyjątków niż metoda w nadklasie.
  • Może zgłaszać mniej lub węższe sprawdzane wyjątki.
  • Może zgłosić dowolne niesprawdzone wyjątki (takie jak RuntimeException) niezależnie od metody nadklasy.
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  ());      }      }   }   

Wyjście
Child method  

Dlaczego używamy przesłaniania metod?

  • Aby zmienić lub ulepszyć zachowanie istniejącej metody w podklasie.
  • Aby osiągnąć polimorfizm w czasie wykonywania — wywołania metod zależą od rzeczywistego typu obiektu.
  • Aby ponownie użyć nazw metod, logicznie zmniejszając redundancję.

Przykład z życia wzięty: System zarządzania pracownikami

Rozumiemy zastąpienie przez analogię ze świata rzeczywistego.

Wyobraź sobie system zarządzania pracownikami organizacji. Wszyscy pracownicy mają wspólne pewne zachowania, takie jak raiseSalary() i promowanie(), ale logika jest inna w przypadku różnych ról, takich jak menedżer czy inżynier. Możemy utworzyć pojedynczą tablicę Employee, w której poszczególni pracownicy należą do różnych typów (technicy sprzedaży itp.) i wywołać ich funkcje. To znacznie upraszcza cały kod.

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  ();      }      }   }   

Wyjście
--- Raising Salaries --- Manager salary raised with incentives. Engineer salary raised with bonus. --- Promotions --- Manager promoted to Senior Manager. Engineer promoted to Senior Engineer.  

Wyjaśnienie: Chociaż zarówno obiekty Menedżera, jak i Inżyniera są określane przy użyciu typu Pracownik, Java wywołuje przesłonięte metody rzeczywistych obiektów w czasie wykonywania, demonstrując dynamiczne wysyłanie metod (polimorfizm środowiska wykonawczego).

Powiązany artykuł: Przeciążanie metod i zastępowanie metod