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.
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.
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 :
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ę.
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ą.
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.
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.
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