здрасти Вие вече използвате Java методи и знаете много за тях. Как работи замяната на метода - 1Със сигурност сте попадали на клас с много методи, които имат едно и също име, но различни списъци с аргументи. Спомняте си, че в тези случаи използвахме претоварване на метода. Днес ще разгледаме една различна ситуация. Представете си, че имаме един общ метод, но той трябва да прави различни неща в зависимост от класа, в който е извикан. Как да приложим това поведение? За да разберем това, нека вземем Animalродителския клас, който представлява животни, и създадем speakметод в него:

public class Animal {
  
   public void speak() {

       System.out.println("Hello!");
   }
}
Въпреки че току-що започнахме да пишем нашата програма, вероятно виждате потенциален проблем: светът е пълен с много животни и всички те „говорят“ по различен начин: котките мяучат, патиците крякат, змиите съскат и т.н. Нашата цел е проста: Как работи замяната на метода - 2ние искате да избегнете създаването на куп методи за говорене. Вместо да създаваме meow()метод за мяукане, hiss()за съскане и т.н., ние искаме змията да съска, котката да мяуче и кучето да лае, когато методът speak()бъде извикан. Можем лесно да постигнем това, като използваме отмяна на метода . Уикипедия обяснява термина по следния начин: Замяна на метода, в обектно-ориентираното програмиране, е езикова характеристика, която позволява на подклас or дъщерен клас да предостави специфична реализация на метод, който вече е предоставен от един от неговите суперкласове or родителски класове. Това по принцип е правилно. Замяната ви позволява да вземете няHowъв метод на родителски клас и да напишете своя собствена реализация във всеки производен клас. Новата реализация в дъщерния клас "замества" тази в родителския. Нека да видим How изглежда това с пример. Нека създадем 4 наследника на нашия 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!");
   }
}
Ето малък лайфхак за бъдещето: за да замените методите на родителски клас, влезте в codeа на производния клас в IntelliJ IDE , натиснете Ctrl+O и изберете Замени методите... от менюто. Свикнете да използвате клавишни комбинации от самото начало. Те ще ускорят codeирането! За да постигнем желаното поведение, направихме няколко неща:
  1. Във всеки клас наследник създадохме метод със същото име като метода в родителския клас.
  2. Казахме на компилатора, че не просто даваме на метода същото име като в родителския клас, а по-скоро искаме да отменим поведението му. Това „съобщение“ към компилатора се предава чрез анотацията @Override .
    Анотацията @Override над даден метод казва на компилатора (Howто и на други програмисти, които четат вашия code): „Не се притеснявайте. Това не е грешка or пропуск. Наясно съм, че този метод вече съществува и искам да го отменя .

  3. Написахме имплементацията, от която се нуждаем за всеки клас наследник. Когато speak()се извика методът, змия трябва да изсъска, мечка да ръмжи и т.н.
Нека да видим How работи това в програма:

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();
   }
}
Изход от конзолата:

Woof! 
Meow! 
Growl! 
Hiss!
Супер, всичко работи Howто трябва! Създадохме 4 референтни променливи, чийто тип е Animalродителският клас, и им присвоихме 4 различни обекта от наследствените класове. В резултат на това всеки обект се държи по различен начин. За всеки от производните класове, замененият speak()метод замества съществуващия speak()метод на Animalкласа (който просто показва „Говоря:“ на конзолата). Как работи замяната на метода - 3Замяната на метода има няколко ограничения:
  1. Отменен метод трябва да има същите аргументи като метода в родителския клас.

    Ако speakметодът на родителския клас приема Stringкато вход, тогава заместеният метод в наследствения клас също трябва да приема Stringкато вход. В противен случай компилаторът ще генерира грешка:

    
    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. Замененият метод трябва да има същия тип връщане като метода в родителския клас.

    В противен случай ще получим грешка при компилация:

    
    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. Модификаторът за достъп на заменения метод също не може да се различава от оригиналния:

    
    public class Animal {
    
       public void speak() {
    
           System.out.println("Hello!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void speak() {      // Error!
           System.out.println("Meow!");
       }
    }
    
В Java замяната на метода е един от начините за прилагане на полиморфизъм. Това означава, че основното му предимство е тази гъвкавост, за която говорихме по-рано. Можем да изградим проста и логична йерархия от класове, всеки със специфично поведение (лаещи кучета, мяукащи котки), но един интерфейс — един speak()метод за всички, а не куп различни методи, напр bark(). meow(), и т.н.