Sobes.tech
Junior

Czym jest nadpisywanie (Overriding) w programowaniu?

sobes.tech AI

Odpowiedź od AI

Przesłanianie metody (Overriding) to możliwość podklasy do dostarczania własnej implementacji metody, która jest już zdefiniowana w jej klasie rodzicielskiej. Sygnatura nadpisywanej metody (nazwa, liczba i typy parametrów) w podklasie musi całkowicie pokrywać się z sygnaturą metody w klasie rodzicielskiej. Typ zwracanego wyniku musi być również taki sam lub być kowariantny (podtyp) typu zwracanego przez metodę w klasie rodzicielskiej.

Główne aspekty nadpisywania:

  • Dziedziczenie: Nadpisywanie jest możliwe tylko w kontekście relacji dziedziczenia, gdzie podklasa dziedziczy metodę od superklasy.
  • Polimorfizm: Nadpisywanie jest jednym z mechanizmów realizacji polimorfizmu czasu wykonywania (runtime polymorphism). Oznacza to, że w zależności od rzeczywistego typu obiektu, wywoływanego przez odwołanie do typu rodzica, będzie wykonywana odpowiednia implementacja metody (zarówno z klasy rodzica, jak i z klasy potomnej).
  • Słowo kluczowe @Override: W niektórych językach (np. Java) używa się adnotacji @Override. Nie jest ona obowiązkowa dla poprawnego działania nadpisywania, ale jest zalecana w celu poprawy czytelności kodu i zapobiegania błędom kompilacji, jeśli metoda nie spełnia zasad nadpisywania.
  • Dostęp do metody rodzica: Wewnątrz nadpisanej metody w podklasie często konieczne jest wywołanie implementacji tej samej metody z klasy rodzica. Do tego służy słowo kluczowe super (np. super.metoda()).

Przykład w Javie:

// Klasa rodzic
class Animal {
    // Metoda w klasie rodzic
    void makeSound() {
        System.out.println("Zwierzę wydaje dźwięk");
    }
}

// Klasa potomna dziedzicząca po Animal
class Dog extends Animal {
    // Nadpisanie metody makeSound()
    @Override
    void makeSound() {
        System.out.println("Hau hau!");
    }

    // Przykład wywołania metody rodzica
    void eat() {
        System.out.println("Pies je.");
        super.makeSound(); // Wywołanie metody z klasy rodzica
    }
}

class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog(); // Polimorfizm

        myAnimal.makeSound(); // Wypisze: Zwierzę wydaje dźwięk
        myDog.makeSound();   // Wypisze: Hau hau! (Wywołanie nadpisanej metody)

        Dog specificDog = new Dog();
        specificDog.eat(); // Wypisze: Pies je. 
                          // Zwierzę wydaje dźwięk
    }
}

Przykład w Pythonie:

# Klasa rodzic
class Animal:
    # Metoda w klasie rodzic
    def make_sound(self):
        print("Zwierzę wydaje dźwięk")

# Klasa potomna dziedzicząca po Animal
class Dog(Animal):
    # Nadpisanie metody make_sound()
    def make_sound(self):
        print("Hau hau!")

    # Przykład wywołania metody rodzica
    def eat(self):
        print("Pies je.")
        super().make_sound() # Wywołanie metody z klasy rodzica

# Demonstracja
my_animal = Animal()
my_dog = Dog() # Polimorfizm

my_animal.make_sound() # Wypisze: Zwierzę wydaje dźwięk
my_dog.make_sound()   # Wypisze: Hau hau!

specific_dog = Dog()
specific_dog.eat() # Wypisze: Pies je. 
                      # Zwierzę wydaje dźwięk

Przesłanianie służy do dostosowania zachowania klasy bazowej do specyfiki klasy pochodnej, zachowując ogólny interfejs. Jest to kluczowy element projektowania obiektowego.