JavaRush /Blog Java /Random-PL /Mechanizm przesłaniania metody lub zastąpienie w Javie

Mechanizm przesłaniania metody lub zastąpienie w Javie

Opublikowano w grupie Random-PL
Cześć! Używasz już metod w Javie i dużo o nich wiesz. Prawdopodobnie spotkałeś się z sytuacją, w której w jednej klasie było wiele metod o tej samej nazwie, ale różnych argumentach. Jeśli pamiętasz, w tych przypadkach używaliśmy mechanizmu przeciążania metody. Dziś spójrzmy na inną sytuację. Wyobraź sobie, że mamy jedną wspólną metodę, ale powinna ona robić różne rzeczy w zależności od klasy, w której została wywołana. Jak zaimplementować to zachowanie? Aby to zrozumieć, weźmy klasę nadrzędną Animaloznaczającą zwierzęta i utwórzmy w niej metodę voice- „ głos ”:
public class Animal {

   public void voice() {

       System.out.println("Głos!");
   }
}
Choć dopiero zaczęliśmy pisać program, już na pewno widać potencjalny problem: zwierząt na świecie jest mnóstwo i każde „mówi” inaczej: koty miauczą, kaczki kwaczą, węże syczą. Jak działa mechanizm nadpisywania metod - 2 Nasz cel jest prosty: uniknąć tworzenia wielu metod głosowania. Zamiast tworzyć metody voiceCat()miauczenia, voiceSnake()syczenia itp., chcemy, aby voice()wąż syczał, kot miauczał, a pies szczekał, gdy metoda zostanie wywołana. Możemy to łatwo osiągnąć za pomocą mechanizmu przesłaniania metod (Override w Javie) . Wikipedia podaje następujące wyjaśnienie terminu „przesłanianie”: Przesłanianie metod w programowaniu obiektowym jest jedną z cech języka programowania, która pozwala podklasie lub klasie potomnej zapewnić specyficzną implementację metody już zaimplementowanej w jednej z nadklas lub zajęcia dla rodziców. Generalnie jest to słuszne. Przesłanianie pozwala na pobranie metody z klasy nadrzędnej i napisanie własnej implementacji tej metody w każdej klasie potomnej. Nowa implementacja „zastąpi” rodzica w klasie podrzędnej. Zobaczmy, jak to wygląda na przykładzie. Stwórzmy 4 klasy następcze dla naszej klasy Animal:
public class Bear extends Animal {
   @Override
   public void voice() {
       System.out.println("Р-р-р!");
   }
}
public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Miauczeć!");
   }
}

public class Dog extends Animal {

   @Override
   public void voice() {
       System.out.println("Wątek!");
   }
}


public class Snake extends Animal {

   @Override
   public void voice() {
       System.out.println("Ш-ш-ш!");
   }
}
Mały lifehack na przyszłość: aby zastąpić metody klasy nadrzędnej, przejdź do kodu klasy potomnej w Intellij IDE a, naciśnij Ctrl+O i wybierz z menu „ Zastąp metody... ”. Przyzwyczaj się do używania skrótów klawiszowych od początku, przyspieszy to pisanie programów! Aby ustawić pożądane zachowanie, zrobiliśmy kilka rzeczy:
  1. W każdej klasie potomnej utworzyliśmy metodę o tej samej nazwie, co metoda w klasie nadrzędnej.
  2. Powiedzieliśmy kompilatorowi, że nie bez powodu nazwaliśmy metodę tak samo jak w klasie nadrzędnej: chcieliśmy zastąpić jej zachowanie. W przypadku tej „wiadomości” do kompilatora umieszczamy adnotację @Override na metodzie .
    Adnotacja @Override umieszczona nad metodą mówi kompilatorowi (i programistom czytającym Twój kod także): „Wszystko jest w porządku, to nie jest błąd ani moje zapomnienie. Pamiętam, że taka metoda już istnieje i chcę ją zastąpić.”

  3. Napisaliśmy implementację, której potrzebowaliśmy dla każdej klasy potomnej. Na wezwanie wąż voice()powinien syczeć, 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.voice();
       animal2.voice();
       animal3.voice();
       animal4.voice();
   }
}
Dane wyjściowe konsoli: Hau! Miauczeć! Mrrr! Ciii! Świetnie, 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 efekcie każdy obiekt zachowuje się inaczej. Dla każdej z klas potomnych przeciążona metoda voice()zastąpiła metodę „natywną” voice()z klasy Animal(która po prostu wyświetla na konsoli komunikat „Głos!”). Jak działa mechanizm nadpisywania metod - 3 Zastępowanie ma wiele ograniczeń:
  1. Przesłonięta metoda musi mieć takie same argumenty jak metoda nadrzędna.

    Jeśli metoda voicew klasie nadrzędnej akceptuje jako dane wejściowe String, nadpisana metoda w klasie potomnej musi również akceptować jako dane wejściowe String, w przeciwnym razie kompilator zgłosi błąd:

    public class Animal {
    
       public void voice(String s) {
    
           System.out.println("Głos!" + s);
       }
    }
    
    public class Cat extends Animal {
    
       @Override//błąd!
       public void voice() {
           System.out.println("Miauczeć!");
       }
    }

  2. Przesłonięta metoda musi mieć ten sam typ zwracany co metoda nadrzędna.

    W przeciwnym razie otrzymamy błąd kompilacji:

    public class Animal {
    
       public void voice() {
    
           System.out.println("Głos!");
       }
    }
    
    
    public class Cat extends Animal {
    
       @Override
       public String voice() {         //błąd!
           System.out.println("Miauczeć!");
           return "Miauczeć!";
       }
    }

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

    public class Animal {
    
       public void voice() {
    
           System.out.println("Głos!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void voice() {      //błąd!
           System.out.println("Miauczeć!");
       }
    }
Nadpisywanie metod w Javie jest jednym z narzędzi umożliwiających realizację idei polimorfizmu (zasada OOP, o której mówiliśmy na ostatnim wykładzie). 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 (szczekanie psów, miauczenie kotów), ale z jednym interfejsem - jedna metoda voice()dla wszystkich zamiast kilku metod itp voiceDog().voiceCat()
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION