Nasleđivanje klasa u Javi

Lekcija 11 od 16 · Java

Nasleđivanje klasa je postupak izgradnje novih klasa na nekim postojećim. Skup nekih osobina i ponašanja objekta koje se mogu naći u postojećim klasama mogu se preneti na nove postupkom nasleđivanja. Za to se koristi službena reč Java jezika "extends".

Sintaksa je:

public class Subklasa_ime extends Superklasa_ime {
    //Atributi
    //Metode
}

Svrha pravljenja podklase (subklase) je proširiti postojeće stanje i ponašanje nadređene klase(superklase). Nadređena klasa se još zove "roditelj" klasa, a podređena klasa "dete" klasa.

Više klasa može biti u hijerarhiji. Ako jedna klasa, npr Klasa_3, nasledi drugu(Klasa_2), a ova, opet neku prethodnu npr. klasu "Klasa_1", onda klasa 3 nasleđuje sve prethodne osobine i metode u hijerarhiji.

Ako bi napravili hijerarhiju klasa koje predstavljaju automobile to bi izgledalo:

Nasleđivanje klasa na primeru automobila
Slika 1: Nasleđivanje klasa na primeru automobila

Video lekcije

VIDEO 1: Nasleđivanje klasa u JAVI

Posmatrajmo npr. klasu koja opisuje neku osobu. Ona bi trebala da ima sledeće atribute: ime, prezime, pol, jmbg, kao i metodu toString koja vraca sve podatke kao jedan String.

public class Osoba {
    String ime;
    String prezime;
    String jmbg;
    String pol;

    public Osoba() {
    }

    public Osoba(String ime, String prezime, String jmbg, String pol) {
        this.ime = ime;
        this.prezime = prezime;
        this.jmbg = jmbg;
        this.pol = pol;
    }

    @Override
    public String toString() {
        return "Osoba{"
            + "\nime=" + ime + "\nprezime=" +
            prezime + "\njmbg=" + jmbg + "\npol=" + pol + "}";
    }
}
Slika 1: Klasa Osoba

Ako bi sada želeli da pravimo klasu koja opisuje nekog učenika(Ucenik), treba da uočimo da će ona imati sve atribute koje su već navedene u klasi Osoba , jer učenik zapravo i jeste neka osoba i još neke atribute pored toga, npr. razred , uspeh itd.

Pošto Java podržava nasleđivanje klasa, mi onda možemo napraviti klasu Ucenik tako da proširuje klasu Osoba, tj. nasleđuje njene osobine i metode. Umesto toga, mogli bismo i pisati klasu Ucenik ispočetka pa osobine i metode iz Osoba ponovo pisati, ali to je lošiji put.

Evo kako bi izgledala klasa Ucenik koja nasleđuje klasu Osoba:

public class Ucenik extends Osoba {
    int razred;
    double uspeh;
    String skola;

    public Ucenik() {
    }

    public Ucenik(String ime, String prezime, String jmbg, String pol,
        int razred, double uspeh, String skola) {
        this.razred = razred;
        this.uspeh = uspeh;
        this.skola = skola;
        // ime, prezime, jmbg i pol se ovde još ne postavljaju – vidi konstruktor sa super(...) niže
    }
}
Slika 2: Nasleđivanje klasa-klasa Ucenik

Zapazite da nisu navedeni atributi koji se nalaze u klasi Osoba: ime,prezime,…Međutim, kada se bude napravio objekat klase Ucenik on će imati u sebi i ove atribute jer su nasleđeni iz klase Osoba. To možemo proveriti tako što napravimo objekat ucenika i kada posle objekta stavimo operator “.” videćemo sve atribute objekta ucenik:

Nasleđivanje klasa: Klasa Nasleđivanje
Slika 3: Klasa Nasleđivanje

Razred,skola i uspeh su istaknuti jer su specificni samo za klasu Ucenik. Ime, prezime, jmbg, poli metoda toString() su nasleđene iz klase Osoba.

Svaka klasa bez obzira što eksplicito ne piše, nasleđuje i klasu Object, koja u sebi ima metode: equals(),hashCode(),notify() itd, tj. sve ostale metode koje se vide na slici iznad.

Prepravljanje metoda u JAVI

Ako pozovemo metodu toString() za objekat ucenik, biće pozvana metoda toString() definisana u klasi Roditelja tj. klasi Osoba, što je logično, jer je ona nasleđena. Ona će vratiti podatke osobe: ime,prezime itd. ali ne i razred, uspeh. U nasleđivanju klasa postoji mogućnost da se ta ista metoda prepravi(override) u klasi Ucenik tako da vraća i podatke o razredu, uspehu. Tada ucenik.toString() poziv metode predstavlja poziv prepravljene metode, a ne nasleđene toString() metode iz klase Osoba. Evo primera upotrebe te metode:Definisanje metode toString():

@Override
public String toString() {
    return "Ucenik{ "
        + "ime=" + ime + "\nprezime=" +
        prezime + "\njmbg=" + jmbg + super.toString() + " }";
}
Slika 4: Metoda toString u klasi Ucenik

i upotreba

public class Nasledjivanje {
    public static void main(String[] args) {
        Ucenik ucenik = new Ucenik("Petar", "Petrovic",
            "1203987710203", "M", 7, 4.8, "Mika Antić");

        System.out.println(ucenik.toString());
    }
}

Izlaz programa (konstruktor klase Ucenik poziva super(ime, prezime, jmbg, pol), kao što je objašnjeno u nastavku):

Ucenik{ ime=Petar
prezime=Petrovic
jmbg=1203987710203Osoba{
ime=Petar
prezime=Petrovic
jmbg=1203987710203
pol=M} }

Slika 5: Klasa Ucenik-main metoda

Pristup atributima i metodama nadređene klase

Ako iz neke klase u datom primeru npr. klase Ucenik želimo da pristupimo atributu ili metodi koja se nalazi u roditelj klasi to možemo uraditi korišćenjem službene reči super.

Upotrebu ove reči vidimo kod konstruktora sa parametrima klase Ucenik

public Ucenik(String ime, String prezime, String jmbg, String pol,
    int razred, double uspeh, String skola) {
    super(ime, prezime, jmbg, pol); // poziv konstruktora roditeljske klase Osoba
    this.razred = razred;
    this.uspeh = uspeh;
    this.skola = skola;
}
Slika 6: Konstruktor klase Ucenik

Unutar konstruktora Ucenik se poziva konstruktor Osoba korišćenjem reči super i njemu se prosleđuju parametri za klasu Osoba, a to su ime,prezime...

Drugi primer je prepravljena metoda toString():

@Override
public String toString() {
    return "Ucenik{ "
        + "razred=" + razred + "\nuspeh=" +
        uspeh + "\nškola=" + skola + super.toString() + " }";
}
Slika 7: Klasa Ucenik-prepravljena(overriding) metoda toString

Treba uočiti da će se podaci o osobi dobiti pozivanjem metode toString() klase osoba. Objekat koji ovde predstavlja osobu je zapravo službena reč „super“.

Poznate hijerarhije klasa

Primer hijerarhije klasa iz API-ja imamo u SWING paketu, a to su klase JButton, JLabel, JTextField.. tj. one klase koje predstavljaju komponente na formi. Evo primera takve hijerarhije:

Nasleđivanje klasa u swing korisničkom paketu
Slika 8: Nasleđivanje klasa u swing korisničkom paketu

Swing komponente nasleđuju klasu JComponent, i jedan takav primer videćemo na sledećoj slici:

Nasleđivanje klase JComponent iz swing korisničkog paketa
Slika 9: Nasleđivanje klase JComponent iz swing korisničkog paketa

Java i fizika

Slika 10: Hijerarhija klasa na primeru iz fizike: Klizanje tela po ravnoj podlozi

Posmatrajmo sledeći problem:

Želimo da simuliramo promenu položaja x pri dejstvu sile na telo koje stoji na horizontalnoj podlozi. Posmatraćemo promene položaja za svaki mali porast vremena od dt[s]. Uzmimo da je ta promena za dt=0.05s.

Telo mase m će iz stanja mirovanja dobiti ubrzanje u x pravcu ax ako je F>Ftr.

Telo mase m se neće kretati u y pravcu (ay=0) jer je N=Fg

gde je:

Fg - Težina tela
N-reakcija podloge

Da bi kretanje simulirali potrebne su nam sile koje deluju na telo.

Kreiraćemo po jedan objekat za svaku silu koja deluje na telo:

F, Ftr,N i Fg

Kreiraćemo po jedan objekat za svaku silu koja deluje na telo:

F, Ftr,N i Fg

Da bi kreirali objekte potrebne su nam klase koje će da ih opišu:

Napravimo prvo klase za silu teže G i silu trenja Ftr.

public class SilaTeze {
    double intenzitet, smer, m;
    String naziv;
    final double G = 9.81;
    public SilaTeze(double smer, double m) {
        this.smer = smer;
        this.m = m;
    }
    public void intenzitet() {
        intenzitet = m * G;
    }
    public void setNaziv(String naziv) {
        this.naziv = naziv;
    }
}
public class SilaTrenja {
    double intenzitet, koefTrenja, N;
    int smer;
    String naziv;
    public SilaTrenja(double koefTrenja, double N) {
        this.koefTrenja = koefTrenja;
        N = n;
    }
    public void intenzitet() {
        intenzitet = koefTrenja * N;
    }
    public void setNaziv(String naziv) {
        this.naziv = naziv;
    }
}

Uočimo sledeće:

  • Obe klase imaju zajedničke osobine naziv,intenzitet i koefPravca kao i metodu setNaziv();
  • Kod obe klase postoji metoda intenzitet(), ali se razlikuju naredbe unutra.
  • Ostale osobine i metode su specifične samo za silu teže a neke samo za silu trenja.

Ako bi te zajedničke osobine izdvojili u posebnu klasu

public class Sila {
    double intenzitet;
    int smer;
    String naziv;
    public Sila(int smer) {
        this.smer = smer;
    }
    public void setNaziv(String naziv) {
        this.naziv = naziv;
    }
}

Tada, klasa SilaTeze, kao i SilaTrenja nasleđuju klasu sila. Posle naziva klase treba dodati

extends Sila

public class SilaTeze extends Sila {
    double m;
    final double G = 9.81;
    public SilaTeze(int smer, double m) {
        super(smer);
        this.smer = smer;
    }
    public void intenzitet() {
        intenzitet = m * G;
    }
}

Podaci naziv i intenzitet

kao i metoda setNaziv()

koji su prebačeni u klasu Sila su sada nasleđeni i biće dodeljeni objektima klase SilaTeze

Nasleđivanje klasa-Sila teže
Slika 11:Nasleđivanje klasa-Sila teže

Da bi sada, testirali ove klase, moramo u test klasi kreirati objekat koji predstavlja silu teže. Objekat će imati sve atribute i metode koje su opisani u klasi, kojoj pomenuti objekat pripada. Da bi smo odabrali neku od osobina ili metoda kreiranog objekta, koristimo operator "." kao na slici ispod.

 Nasleđivanje klasa, prikaz osobina i metoda objekta
Slika 12: Nasleđivanje klasa, prikaz osobina i metoda objekta

U prozoru koji se otvorio, kada smo posle reference objekta stavili tačku, vidimo osbine i metode, kako one što su direktno pisane u klasi SilaTeže, tako i sve one nasleđene iz prethodnih klasa u hijerarhiji. Tako npr. intenzitet je nasleđena osobina iz klase Sila, dok je toString() nasleđena metoda iz klase Object.

 Hijerarhija klasa na primeru sila- UML dijagram
Slika 13: Hijerarhija klasa na primeru sila- UML dijagram

Primer:Za masu tela m=3kg kreirati objekat sile teže, dati mu naziv, izračunati intenzitet sile i prikazati na ekranu.

public class AnalizaSilaTest {
    public static void mainString[](args) {
        SilaTeze teza = new SilaTeze(1, 3);
        teza.setNaziv("Sila teze");
        teza.intenzitet();
        System.out.println(teza.naziv + " iznosi " + teza.intenzitet() + " N");
    }
}

Prvo je kreiran objekat teza koji pripada klasi SilaTeze, gde je upotrebljen konstruktor sa parametrima, gde se kao parametri šalju smer vektora i masa tela. Zatim se preko reference objekta pozivaju metode setNaziv() i intenzitet(). Metoda intenzitet je metoda koja izračunava intenzitet, ali nema nikakvu povratnu vrednost(void). U poslednjem koraku se prikazuju izračunate vrednosti na standardni izlaz.

Prepravljanje metoda(engl. overriding)

Sve klase nasleđuju klasu Object, tako da su nasledile sve njene metode.

Metoda toString() je jedna od nasleđenih metoda iz Object klase, i predviđena je da formira tekst za prikaz podataka iz objekta kome pripada.

Međutim, u telu te metode koja je napisana u klasi Object nema ništa jer u toj klasi nema podataka, zato se metoda toString() prepravlja u klasi koja je nasledi, u našem slučaju to su Sila i kasnije SilaTeže.

Prepravljanje (engl. overriding) metoda
Slika 14: Prepravljanje (engl. overriding) metoda
Ovde nam je ponuđena klasa Object jer smo nju nasledili. Štikliramo toString() od ponuđenih metoda i kliknemo na OK dugme
 Prepravljanje metoda - izbor
Slika 15: Prepravljanje metoda - izbor

Posle zatvaranja dijaloga, generisana je metoda toString i sada, u telu metode mi treba da prilagodimo da se prikazuju podaci za silu.

Selektovano super.toString() zamenjujemo sa

naziv+” iznosi ”+intenzitet+“[N]

public void setNaziv(String naziv) {
    this.naziv = naziv;
}

@Override
public String toString() {
    // TODO Auto-generated method stub
    return super.toString(); // ovo zamenjujemo tekstom sa podacima o sili
}
Slika 16: Poziv nasleđene toString() metode, u klasi SilaTeze, upotrebom reči "super"

u klasi Sila, pozivom metode toString() prikazaće se tekst koji prikazuje podatke iz objekta

public class Sila {
    double intenzitet;
    int smer;
    String naziv;

    public Sila(int smer) {
        ...
    }

    public void setNaziv(String naziv) {
        ...
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return naziv + " " + intenzitet + "N";
    }
}

Tela konstruktora i metode setNaziv su skupljena (...), kao u okruženju na slici.

Slika 17: Poziv nasleđene toString() metode, u klasi Sila, upotrebom reči "super"

Preko objekta sile teže se poziva toString( ) i ona vraća pripremljen tekst za ispisivanje

public class AnalizaSilaTest {
    public static void main(String[] args) {
        SilaTeze teza = new SilaTeze(1, 3); // smer i masa
        teza.setNaziv("Sila teže");
        teza.intenzitet();
        //      System.out.println(teza.naziv
        //              + " iznosi " + teza.intenzitet + " N");
        System.out.println(teza.toString());
    }
}
Slika 18: Poziv toString() metode, u test klasi, preko objekta "teža"

Posle pokretanja prikazuje se izračunat intenzitet

Izlaz programa:

Sila teže 29.43N
Slika 19: Poziv toString() metode, u test klasi, preko objekta "teža"-Pokretanje

Primer 2: Telo mase m miruje na horizontalnoj podlozi i na njega u jednom trenutku počne da deluje konstantna sila F u pravcu x ose; Odrediti na kom položaju u odnosu na početni će se naći centar mase tela posle vremena t. Koeficijent trenja je 0,05. Kreirati objekte koji predstavljaju redom sve sile na telo koristeći nasleđivanje klasa. Ispisati intenzitete svih sila. Uzeti za pozitivne vrednosti intenzitete ako deluju u pravcu koo osa.

Proveri znanje

Otvori kviz

Kviz: Nasleđivanje

1. Šta znači class Ucenik extends Osoba?




2. Čemu služi super(...) u konstruktoru?




3. Šta je prepravljanje (override) metode?




4. Od koje klase u Javi nasleđuju sve klase?