Nadređivanje metoda

Izvor: Wikipedija
Ovo je članak o klasnim metodama s istim imenom i parametrima pri nasljeđivanju. Za istoimene funkcije koje primaju različite parametre pogledajte članak Preopterećenje funkcija.
Ilustracija nadklase Animal (životinja) i podklase Dog (pas), koja naslijeđuje metodu eat, ali nadređuje metodu move().

Nadređivanje metoda (en. method overriding), također premošćivanje metoda, u objektno orijentiranom programiranju, mogućnost je programskog jezika koja omogućuje naslijeđenoj podklasi (djetetu) da pruži specifičniju implementaciju metode koja je već definirana u nadklasi (roditelju).

Implementacija istoimene metode u podklasi nadređuje (zamjenjuje) implementaciju u nadklasi samo ako metoda ima isti funkcijski potpis (isto ime, isti tip i broj parametara te isti povratni tip).[1] Metodu koja će se izvršiti odabire kompilator pri izvršavanju programa, ovisno o objektu koji metodu poziva. Ako roditeljska klasa instancira objekt, pozvat će se metoda roditeljske klase. Suprotno tome, ako je objekt instanca naslijeđene klase, bit će izvedena inačica metode u podklasi.[2]

Neki programski jezici dopuštaju programeru da ručno ograniči nadređivanje metoda.

Primjeri po jezicima[uredi | uredi kôd]

C#[uredi | uredi kôd]

C# podržava nadređivanje, ali samo ako je ono eksplicitno zatraženo putem modifikatora override i virtual ili abstract.

abstract class Zivotinja
{
    public          string Ime { get; set; }
    // metode
    public          void   Pij();
    public virtual  void   Jedi();
    public          void   Idi();
}

class Pas : Zivotinja
{
    public new      string Ime { get; set; }
    // metode
    public          void   Pij();   // skriva naslijeđenu metodu pij(). Koristi new za pristup
    public override void   Jedi();  // Nadređuje naslijeđenu metodu jedi()
    public new      void   Idi();   // skriva naslijeđenu metodu idi()
}

Potpisi nadređenih metoda moraju biti identični, i metode moraju imati istu vidljivost. C# dopušta nadređivanje metoda, indeksera, svojstava i događaja.

Ne-virtualne ili statičke metode ne mogu se nadrediti. Bazna klasa uvijek mora imati jedan od modifikatora virtual, abstract, ili override.

Prikrivanje imena[uredi | uredi kôd]

Uz gorenavedene modifikatore, C# dopušta prikrivanje naslijeđenog svojstva ili metode, ako metoda ili svojstvo ima jednak potpis, ali koristi modifikator new.[3]

U gornjem primjeru, zbog prikrivanja se događa sljedeće:

Pas pas = new Pas();

pas.Ime = ;             // pristupa Pas.Ime
pas.Jedi();                // poziva Pas.Jedi()
pas.Idi();                 // poziva Pas.Idi()
((Zivotinja)pas).Ime = ;   // poziva Zivotinja.Ime!
((Zivotinja)pas).Jedi();      // poziva Pas.Jedi()!
((Zivotinja)pas).Idi();       // poziva Zivotinja.Idi()!

C++[uredi | uredi kôd]

C++ zahtjeva eksplicitno definiranje imena klase čiju metodu želimo pozvati, pomoću en. scope resolution operator – „operatora razrješenja dosega”, ::. Primjerice, idući kod stvara dvije naslijeđene klase, baznu klasu Pravokutnik (koji može ispisati svoju duljinu i širinu) i naslijeđenu klasu Kutija (koja ima još i visinu). Kutija nadređuje metodu za ispis, kako bi ispisala svoje tri dimenzije.[4]

#include <iostream>

//---------------------------------------------------------------------------
class Pravokutnik {
 public:
  Pravokutnik(double d, double s) : duljina_(d), sirina_(s) {}
  virtual void Ispis() const;

 private:
  double duljina_;
  double sirina_;
};

//---------------------------------------------------------------------------
void Pravokutnik::Ispis() const {
  // metoda za ispis bazne klase.
  std::cout << "Duljina = " << duljina_ << "; Širina = " << sirina_;
}

//---------------------------------------------------------------------------
class Kutija : public Pravokutnik {
 public:
  Kutija(double d, double s, double v) : Pravokutnik(d, s), visina_(v) {}
  void Ispis() const override;

 private:
  double visina_;
};

//---------------------------------------------------------------------------
// metoda za ispis naslijeđene klase
void Kutija::Ispis() const {
  // Pozovi roditeljsku metodu za ispis
  Pravokutnik::Ispis();     // ispisuje duljinu i širinu
  std::cout << "; Visina = " << visina_;
}

Metoda za ispis klase Kutija, pozivanjem metode ispis klase Pravokutnik, može ispisati privatne članske varijable duljina i sirina, koje bi joj inaće bile nedostupne.

Iduće će naredbe instancirati objekte tipa Pravokutnik i Kutija, i pozvati njihove metode za ispis:

int main(int argc, char** argv) {
  Pravokutnik p(5.0, 3.0);

  // Ispisuje: Duljina = 5.0; Širina = 3.0
  p.Ispis();

  Kutija k(6.0, 5.0, 4.0);

  // pokazivač na najviše nadređenu metodu u virtualnoj tablici je na Kutija::Ispis,
  // ali to ne demonstrira nadređivanje
  k.Ispis();

  // Ovaj poziv demonstrira nadređenje
  // ispisuje: Duljina = 6.0; Širina = 5.0; Visina= 4.0
  static_cast<Pravokutnik&>(k).Ispis();
}

U C++11, slično kao u Javi, metoda sa modifikatorom final u nadklasi ne može se nadrediti. Metodama u podklasi se također može nadjenuti modifikator override, kako bi kompilator provjerio nadređuje li metoda zaista neku metodu bazne klase.

Java[uredi | uredi kôd]

U Javi, kada podklasa sadrži metodu koja nadređuje metodu nadklase, metoda podklase može pozvati metodu nadklase koristeći ključnu riječ super.[2] Primjer:

class Misao {
    public void poruka() {
        System.out.println("Osjećam da sam parkiran dijagonalno u paralelnom svemiru.");
    }
}

public class Savjet extends Misao {
    @Override  // anotacija @Override nije nužna u Javi 5
    public void poruka() {
        System.out.println("Savjet: Datumi u kalendaru bliže su nego što izgleda.");
    }
}

Klasa Misao je nadklasa, i implementira poziv metode poruka. Podklasa Savjet nasljeđuje sve metode klase Misao, i nadređuje metodu poruka, jer joj pruža drugu funkcionalnost.

Misao parking = new Misao();
parking.poruka();  // Ispisuje "Osjećam da sam parkiran dijagonalno u paralelnom svemiru."

Misao datumi = new Savjet();  // Polimorfizam
datumi.poruka();  // Ispisuje "Savjet: Datumi u kalendaru bliže su nego što izgleda."

Poziv nadređene metode unutar podklase može se napisati kao:

public class Savjet extends Misao {
      @Override
      public void poruka() {
          System.out.println("Savjet: Datumi u kalendaru bliže su nego što izgleda.");
          super.poruka();  // Poziva inačicu metode roditeljske klase (Misao.poruka()).
      }

Postoje metode koje podklasa ne može nadrediti. To uključuje[5]:

  • metode u nadklasi koje imaju modifikator final
  • metode s modifikatorima private ili static jer im je implicitno dodjeljen i modifikator final
  • klasa ne može naslijediti drugu klasu s modifikatorom final (klase s modifikatorom final ne mogu biti nadklase)

Python[uredi | uredi kôd]

Ako podklasa u Python, sadrži metodu koja premošćuje metodu nadklase, moguće je eksplicitno pozvati metodu nadklase pozivom super(Subclass, self).method [6] umjesto self.method. Primjer:

class Misao:
    def __init__(self) -> None:
        print("Ja sam novi objekt tipa Misao!")
    def poruka(self) -> None:
        print("Osjećam da sam parkiran dijagonalno u paralelnom svemiru.")

class Savjet(Misao):
    def __init__(self) -> None:
        super(Savjet, self).__init__()
    def poruka(self) -> None:
        print("Savjet: Datumi u kalendaru bliže su nego što izgleda.")
        super(Savjet, self).poruka()

t = Misao()
# ispisuje "Ja sam novi objekt tipa Misao!"
t.poruka()
# ispisuje "Osjećam da sam parkiran dijagonalno u paralelnom svemiru.

a = Savjet()
# ispisuje "Ja sam novi objekt tipa Misao!"
a.poruka()
# ispisuje "Savjet: Datumi u kalendaru bliže su nego što izgleda."
# zatim ispisuje "Osjećam da sam parkiran dijagonalno u paralelnom svemiru.

# ------------------
# provjera:

isinstance(t, Misao)
# True

isinstance(a, Savjet)
# True

isinstance(a, Misao)
# True

Bilješke[uredi | uredi kôd]

  1. Flanagan 2002, str. 107
  2. a b Lewis & Loftus 2006, str. 454
  3. Mössenböck, Hanspeter. 25. ožujka 2002. Advanced C#: Overriding of Methods (PDF). Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. str. 6–8. Pristupljeno 2. kolovoza 2011.
  4. Malik 2006, str. 676
  5. Deitel & Deitel 2001, str. 474
  6. ili super().method u Pythonu 3 - vidi https://docs.python.org/3/library/functions.html#superArhivirana inačica izvorne stranice od 26. listopada 2018. (Wayback Machine)

Vidi još[uredi | uredi kôd]

Izvori[uredi | uredi kôd]

  • Deitel, H. M & Deitel, P. J.(2001). Java How to Program (4th ed.). Upper Saddle River, NJ: Prentice Hall.
  • Lewis, J. & Loftus, W. (2008). Java: Software Solutions (6th ed.). Boston, MA: Pearson Addison Wesley.
  • Malik, D. S.(2006). C++ Programming: Program Design Including Data Structure. (3rd ed.). Washington, DC: Course Technology.
  • Flanagan, David.(2002).Java in a Nutshell. Dohvaćeno sa http://oreilly.com/catalog/9780596002831/preview#preview
  • Meyer, Bertrand (2009). Touch of Class: Learning to Program Well with Objects and Contracts. Springer.

Vanjske poveznice[uredi | uredi kôd]