OBJEKTINIS PROGRAMAVIMAS

Java paveldėjimas

Paveldėjimas leidžia naujai klasei perimti kitos klasės laukus ir metodus. Taip bendras kodas laikomas bazinėje klasėje, o specializuotos klasės jį papildo arba pritaiko.

Superclass ir subclass

Pagrindinės Java paveldėjimo sąvokos
SąvokaLietuviškaiPaskirtis
SuperclassBazinė arba tėvinė klasėKlasė, kurios nariai paveldimi
SubclassIšvestinė arba vaikinė klasėKlasė, kuri paveldi ir papildo bazinę klasę

Java klasė kitą klasę paveldi naudodama raktažodį extends.

Paveldėjimas su extends

Paprastas kasdienis pavyzdys: knyga yra viena iš leidinio rūšių, todėl klasė Knyga gali paveldėti klasę Leidinys.

class Leidinys {
    protected String pavadinimas = "Mažasis princas";

    public void rodytiPavadinima() {
        System.out.println("Leidinys: " + pavadinimas);
    }
}

class Knyga extends Leidinys {
    private int puslapiuSkaicius = 96;

    public void rodytiPuslapius() {
        System.out.println("Puslapių: " + puslapiuSkaicius);
    }

    public static void main(String[] args) {
        Knyga knyga = new Knyga();
        knyga.rodytiPavadinima();
        knyga.rodytiPuslapius();
    }
}
Konsolės rezultatas

Leidinys: Mažasis princas
Puslapių: 96

  1. class Leidinys aprašo tai, ką turi visi leidiniai: pavadinimą ir jo parodymo metodą.
  2. class Knyga extends Leidinys pasako, kad knyga perima prieinamus Leidinys narius.
  3. Knyga papildomai turi savo lauką puslapiuSkaicius ir metodą rodytiPuslapius().
  4. Sukurtas Knyga objektas gali iškviesti ir paveldėtą, ir savo metodą.

Paveldėtų narių naudojimas

class Leidinys {
    protected String kategorija = "Vaikų literatūra";

    public void rodytiKategorija() {
        System.out.println("Kategorija: " + kategorija);
    }
}

class Knyga extends Leidinys {
    public void rodytiInformacija() {
        rodytiKategorija();
        System.out.println("Kategorijos pavadinime yra "
                + kategorija.length() + " simbolių.");
    }

    public static void main(String[] args) {
        Knyga knyga = new Knyga();
        knyga.rodytiInformacija();
    }
}
Konsolės rezultatas

Kategorija: Vaikų literatūra
Kategorijos pavadinime yra 16 simbolių.

  1. Knyga paveldi protected lauką kategorija ir viešą metodą rodytiKategorija().
  2. Metodas rodytiInformacija() pirmiausia iškviečia paveldėtą metodą.
  3. Tada jis tiesiogiai panaudoja paveldėtą protected lauką ir suskaičiuoja teksto simbolius.
private nariai tiesiogiai poklasiui nepasiekiami.

Bazinė klasė gali juos apsaugoti ir suteikti kontroliuojamą prieigą per protected arba viešus metodus.

Bazinės klasės konstruktorius

super(...) iškviečia bazinės klasės konstruktorių ir turi būti pirmoji poklasio konstruktoriaus instrukcija:

class Leidinys {
    protected String pavadinimas;

    Leidinys(String pavadinimas) {
        this.pavadinimas = pavadinimas;
    }
}

class Knyga extends Leidinys {
    private int puslapiuSkaicius;

    Knyga(String pavadinimas, int puslapiuSkaicius) {
        super(pavadinimas);
        this.puslapiuSkaicius = puslapiuSkaicius;
    }

    public void rodytiInformacija() {
        System.out.println(pavadinimas + ": "
                + puslapiuSkaicius + " puslapiai");
    }

    public static void main(String[] args) {
        Knyga knyga = new Knyga("Mažasis princas", 96);
        knyga.rodytiInformacija();
    }
}
Konsolės rezultatas

Mažasis princas: 96 puslapiai

  1. Kuriant Knyga objektą konstruktorius gauna pavadinimą ir puslapių skaičių.
  2. super(pavadinimas) perduoda pavadinimą bazinės klasės Leidinys konstruktoriui.
  3. Bazinė klasė išsaugo bendrą pavadinimą, o Knyga išsaugo tik jai reikalingą puslapių skaičių.

Paveldėto metodo perrašymas

Poklasis gali pateikti savo paveldėto metodo realizaciją:

class Leidinys {
    public void rodytiTipa() {
        System.out.println("Tai yra leidinys");
    }
}

class Knyga extends Leidinys {
    @Override
    public void rodytiTipa() {
        System.out.println("Tai yra knyga");
    }

    public static void main(String[] args) {
        Leidinys leidinys = new Leidinys();
        Knyga knyga = new Knyga();

        leidinys.rodytiTipa();
        knyga.rodytiTipa();
    }
}
Konsolės rezultatas

Tai yra leidinys
Tai yra knyga

  1. Leidinys pateikia bendrą metodo rodytiTipa() elgesį.
  2. Knyga paveldi šį metodą, tačiau jį perrašo savo versija.
  3. @Override padeda kompiliatoriui patikrinti, ar toks metodas tikrai yra bazinėje klasėje.
  4. Todėl tas pats metodo pavadinimas skirtingiems objektams gali pateikti skirtingą rezultatą.

Kada naudoti paveldėjimą?

  • Kai poklasis iš tiesų yra konkretesnė bazinės klasės rūšis.
  • Kai kelios klasės dalijasi bendra būsena ir elgsena.
  • Kai bendras kodas gali būti prižiūrimas vienoje bazinėje klasėje.
  • Kai paveldėtas elgesys turi būti specializuojamas perrašant metodus.

Paveldėjimas neturėtų būti naudojamas vien tam, kad būtų pasiektas svetimas kodas. Jei objektai nėra natūraliai susiję ryšiu „yra“, dažnai tinkamesnė kompozicija – vieno objekto laikymas kito objekto lauke.

Paveldėjimo ribojimas su final

final klasė negali turėti poklasių:

final class BibliotekosKortele {
}

// Klaida: final klasės paveldėti negalima
class SpecialiKortele extends BibliotekosKortele {
}
Kompiliatoriaus klaida

error: cannot inherit from final BibliotekosKortele

BibliotekosKortele pažymėta final, todėl Java neleidžia sukurti ją paveldinčios klasės.

final taip pat gali uždrausti konkretaus metodo perrašymą:

class Leidinys {
    public final void rodytiIsbn() {
        System.out.println("ISBN: 978-609-00-0000-0");
    }
}

class Knyga extends Leidinys {
    @Override
    // Klaida: final metodo perrašyti negalima
    public void rodytiIsbn() {
    }
}
Kompiliatoriaus klaida

error: rodytiIsbn() in Knyga cannot override rodytiIsbn() in Leidinys
overridden method is final

Poklasis paveldi final metodą ir gali jį naudoti, tačiau negali pakeisti jo veikimo.

Svarbios Java paveldėjimo taisyklės

  • Klasė tiesiogiai gali paveldėti tik vieną kitą klasę.
  • Visos klasės tiesiogiai arba netiesiogiai paveldi Object.
  • Konstruktoriai nepaveldimi, tačiau poklasio konstruktorius iškviečia bazinės klasės konstruktorių.
  • private nariai nėra tiesiogiai pasiekiami poklasyje.
  • Poklasis gali pridėti savo laukus ir metodus bei perrašyti leidžiamus metodus.