Cześć! Używasz już metod w Javie i dużo o nich wiesz. Jak działa mechanizm nadpisywania metody - 1Na pewno spotkałeś się z sytuacją, gdy w jednej klasie było wiele metod o tej samej nazwie, ale różnych argumentach. Jak pamiętacie, w tych przypadkach stosowaliśmy mechanizm przeciążania metod. Przyjrzyjmy się dzisiaj innej sytuacji. Wyobraź sobie, że mamy jedną wspólną metodę, ale powinna robić różne rzeczy w zależności od klasy, w której została wywołana. Jak wdrożyć takie zachowanie? Aby to zrozumieć, weźmy klasę nadrzędną Animaloznaczającą zwierzęta i stwórzmy w niej metodę speak- „ głos ”:
public class Animal {

   public void speak() {

       System.out.println("Hello!");
   }
}
Chociaż dopiero zaczęliśmy pisać program, potencjalny problem najprawdopodobniej jest już dla Ciebie widoczny: zwierząt na świecie jest bardzo dużo i wszystkie „mówią” inaczej: koty miauczą, kaczki kwaczą, węże syczą. Jak działa mechanizm nadpisywania metody - 2 Nasz cel jest prosty: unikać tworzenia mnóstwa metod głosowania. Zamiast tworzyć metody meow()miauczenia, hiss()syczenia itp., chcemy, aby speak()wąż syczał, kot miauczał, a pies szczekał, gdy metoda zostanie wywołana. Możemy to łatwo osiągnąć za pomocą mechanizmu nadpisywania metody (Override w Javie) . Wikipedia podaje wyjaśnienie terminu „przesłanianie” : Przesłanianie metody) w programowaniu obiektowym, jedna z cech języka programowania, która pozwala podklasie lub klasie potomnej na zapewnienie określonej implementacji metody już zaimplementowanej w jednej z nadklas lub klas nadrzędnych. Generalnie jest to poprawne. Przesłanianie pozwala ci wziąć jakąś metodę klasy nadrzędnej i napisać własną implementację tej metody w każdej klasie pochodnej. Nowa implementacja „zastąpi” rodzica w klasie potomnej. Zobaczmy jak to wygląda na przykładzie. Stwórzmy 4 klasy potomne dla naszej klasy Animal:
public class Bear extends Animal {
   @Override
   public void speak() {
       System.out.println("Growl!");
   }
}
public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void speak() {
       System.out.println("Woof!");
   }
}


public class Snake extends Animal {

   @Override
   public void speak() {
       System.out.println("Hiss!");
   }
}
Mały hack na przyszłość: aby nadpisać metody klasy nadrzędnej, przejdź do kodu klasy pochodnej w Intellij IDE a, naciśnij Ctrl+O i wybierz z menu „ Zastąp metody… ”. Przyzwyczaj się od początku do używania skrótów klawiszowych, przyspiesza to pisanie programów! Aby ustawić pożądane zachowanie, wykonaliśmy kilka czynności:
  1. Stworzyliśmy metodę w każdej klasie potomnej o tej samej nazwie, co metoda w klasie nadrzędnej.
  2. Powiedzieliśmy kompilatorowi, że nie tylko wywołaliśmy tę metodę tak samo, jak w klasie nadrzędnej: chcemy nadpisać jej zachowanie. W przypadku tej „wiadomości” do kompilatora umieszczamy adnotację @Override („przesłonięta”) nad metodą.
    Adnotacja @Override nad metodą mówi kompilatorowi (a także programistom, którzy czytają twój kod): „W porządku, to nie jest błąd ani moje zapomnienie. Pamiętam, że istnieje już taka metoda i chcę ją zastąpić.

  3. Napisaliśmy implementację, której potrzebujemy dla każdej klasy potomnej. Wąż powinien syczeć na wezwanie speak(), niedźwiedź warczeć itp.
Zobaczmy jak to będzie działać w programie:
public class Main {

   public static void main(String[] args) {

       Animal animal1 = new Dog();
       Animal animal2 = new Cat();
       Animal animal3 = new Bear();
       Animal animal4 = new Snake();

       animal1.speak();
       animal2.speak();
       animal3.speak();
       animal4.speak();
   }
}
Wyjście konsoli:

Woof! 
Meow! 
Growl! 
Hiss!
Super, wszystko działa jak należy! Stworzyliśmy 4 zmienne referencyjne klasy nadrzędnej Animali przypisaliśmy je do 4 różnych obiektów klas potomnych. W rezultacie każdy obiekt zachowuje się inaczej. Dla każdej z klas pochodnych nadpisana metoda speak()zastąpiła metodę „natywną” speak()z klasy Animal(która wypisuje tylko „Głos!” na konsoli). Jak działa mechanizm nadpisywania metody - 3 Zastąpienie ma szereg ograniczeń:
  1. Metoda nadpisana musi mieć takie same argumenty jak metoda nadrzędna.

    Jeśli speakmetoda klasy nadrzędnej akceptuje jako input String, zastąpiona metoda w klasie potomnej musi również akceptować jako input String, w przeciwnym razie kompilator zgłosi błąd:

    public class Animal {
    
       public void speak(String s) {
    
           System.out.println("Speaking: " + s);
       }
    }
    
    public class Cat extends Animal {
    
       @Override // Error!
       public void speak() {
           System.out.println("Meow!");
       }
    }

  2. Zastąpiona metoda musi mieć ten sam zwracany typ co metoda nadrzędna.

    W przeciwnym razie otrzymamy błąd kompilacji:

    public class Animal {
    
       public void speak() {
    
           System.out.println("Hello!");
       }
    }
    
    
    public class Cat extends Animal {
    
       @Override
       public String speak() {         // Error!
           System.out.println("Meow!");
           return "Meow!";
       }
    }

  3. Modyfikator dostępu przesłoniętej metody również nie może różnić się od „oryginalnego”:

    public class Animal {
    
       public void speak() {
    
           System.out.println("Hello!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void speak() {      // Error!
           System.out.println("Meow!");
       }
    }
Nadpisywanie metod w Javie jest jednym z narzędzi realizacji idei polimorfizmu. Dlatego główną zaletą korzystania z niego będzie ta sama elastyczność, o której mówiliśmy wcześniej. Możemy zbudować prosty i logiczny system klas, z których każda będzie miała określone zachowanie (psy szczekają, koty miauczą), ale jeden interfejs - jedna metoda speak()dla wszystkich zamiast wielu metod itp bark().meow()