Hoi! U gebruikt al Java-methoden en weet er veel van. Hoe methode-overriding werkt - 1Je bent vast wel eens een klasse tegengekomen met veel methoden die dezelfde naam hebben maar verschillende argumentlijsten. U zult zich herinneren dat we in die gevallen method overloading gebruikten. Vandaag bekijken we een andere situatie. Stel je voor dat we één gemeenschappelijke methode hebben, maar dat deze verschillende dingen zou moeten doen, afhankelijk van de klasse waarin hij wordt aangeroepen. Hoe implementeren we dit gedrag? Om dit te begrijpen, nemen we de Animalouderklasse, die dieren vertegenwoordigt, en maken speaker een methode in:

public class Animal {
  
   public void speak() {

       System.out.println("Hello!");
   }
}
Hoewel we net zijn begonnen met het schrijven van ons programma, zie je waarschijnlijk een potentieel probleem: de wereld is vol met veel dieren, en ze "spreken" allemaal anders: katten miauwen, eenden kwaken, slangen sissen, enz. Ons doel is simpel: Hoe methode-overriding werkt - 2we wil voorkomen dat je een heleboel methoden voor spreken creëert. In plaats van een meow()methode te creëren voor miauwen, hiss()sissen, enz., willen we dat de slang sist, de kat miauwt en de hond blaft wanneer de speak()methode wordt aangeroepen. We kunnen dit eenvoudig bereiken door methode te overschrijven . Wikipedia legt de term als volgt uit: Method overriding, in objectgeoriënteerd programmeren, is een taalfunctie waarmee een subklasse of onderliggende klasse een specifieke implementatie kan bieden van een methode die al wordt geleverd door een van zijn superklassen of bovenliggende klassen. Dat klopt in de basis. Met overschrijven kunt u een methode van een bovenliggende klasse nemen en uw eigen implementatie in elke afgeleide klasse schrijven. De nieuwe implementatie in de onderliggende klasse "vervangt" die in de bovenliggende klasse. Laten we eens kijken hoe dit eruit ziet met een voorbeeld. Laten we 4 afstammelingen van onze Animalklasse maken:

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!");
   }
}
Hier is een kleine lifehack voor de toekomst: om de methoden van een bovenliggende klasse te overschrijven, gaat u naar de code van de afgeleide klasse in IntelliJ IDE , drukt u op Ctrl+O en selecteert u Methoden overschrijven... in het menu. Wen vanaf het begin aan het gebruik van sneltoetsen. Ze zullen het coderen versnellen! Om het gewenste gedrag te krijgen hebben we een aantal dingen gedaan:
  1. In elke onderliggende klasse hebben we een methode gemaakt met dezelfde naam als de methode in de bovenliggende klasse.
  2. We hebben de compiler verteld dat we de methode niet alleen dezelfde naam geven als in de ouderklasse, maar dat we het gedrag ervan willen overschrijven. Dit "bericht" aan de compiler wordt overgebracht via de @Override- annotatie.
    De @Override-annotatie boven een methode vertelt de compiler (evenals andere programmeurs die je code lezen): "Maak je geen zorgen. Dit is geen vergissing of vergissing. Ik ben me ervan bewust dat deze methode al bestaat en ik wil deze negeren. .

  3. We hebben de implementatie geschreven die we nodig hebben voor elke afstammelingenklasse. Als de speak()methode wordt aangeroepen, hoort een slang te sissen, een beer te grommen, enzovoort.
Laten we eens kijken hoe dit werkt in een programma:

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

Woof! 
Meow! 
Growl! 
Hiss!
Super, alles werkt zoals het hoort! We hebben 4 referentievariabelen gemaakt waarvan het type de Animalbovenliggende klasse is, en hebben ze 4 verschillende objecten van de onderliggende klassen toegewezen. Hierdoor gedraagt ​​elk object zich anders. Voor elk van de afgeleide klassen vervangt de overschreven speak()methode de bestaande speak()methode van de Animalklasse (die gewoon "Speaking:" weergeeft op de console). Hoe methode-overriding werkt - 3Methode overschrijven heeft verschillende beperkingen:
  1. Een overschreven methode moet dezelfde argumenten hebben als de methode in de bovenliggende klasse.

    Als de speakmethode van de bovenliggende klasse a Stringals invoer heeft, dan moet de overschreven methode in de afstammende klasse ook a Stringals invoer hebben. Anders genereert de compiler een fout:

    
    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. De overschreven methode moet hetzelfde retourtype hebben als de methode in de bovenliggende klasse.

    Anders krijgen we een compilatiefout:

    
    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. De toegangsmodifier van de overschreven methode kan ook niet verschillen van de originele:

    
    public class Animal {
    
       public void speak() {
    
           System.out.println("Hello!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void speak() {      // Error!
           System.out.println("Meow!");
       }
    }
    
In Java is methode-overriding een manier om polymorfisme te implementeren. Dat betekent dat het belangrijkste voordeel die flexibiliteit is waar we het eerder over hadden. We kunnen een eenvoudige en logische hiërarchie van klassen bouwen, elk met specifiek gedrag (blaffende honden, miauwende katten) maar een enkele interface — een enkele speak()methode voor iedereen in plaats van een heleboel verschillende methoden, bijv bark(). , meow(), enz.