Duboko razumevanje nasleđivanja u Javi
„Sanmej, danas nastavljamo sa učenjem jedne od tri glavne odlike Jave: nasleđivanjem. Već smo se sreli sa tim pojmom kada smo učili o apstraktnim klasama, ali danas ćemo o njemu porazgovarati ozbiljno i detaljno." Nakon što sam sporo izgovorio taj uvodni pasus, dao sam Sanmej gestom znak da otvorite XMind (u stvari, samo sam tako mahao rukama).
„Razumem, brate, odmah otvaram." Govoreći to, Sanmej je otvorila XMind i seo je uspravno i pažljivo.
Kada govorimo o Java objektnoj orijentaciji, moramo spomenuti njene tri glavne odlike: enkapsulaciju, nasleđivanje i polimorfizam. Tri odlike su usko povezane, ali se međusobno razlikuju; razumno korišćenje nasleđivanja znatno smanjuje ponavljanje koda i povećava mogućnost njegovog ponovnog iskorišćenja.

01. Šta je nasleđivanje
Nasleđivanje (engleski: inheritance) pojam je iz tehnologije objektno orijentisanog softvera. Ono čini ponovno iskorišćavanje ranijeg koda vrlo lakim.
Java je tipičan objektno orijentisani jezik; u Javi nasleđivanje znači da podklasa nasleđuje osobine i metode roditeljske klase, čime objekat podklase (instanca) dobija osobine i metode roditeljske klase, ili podklasa iz roditeljske klase nasleđuje metode tako da ima iste metode kao roditeljska klasa.
Uzmimo primer: postoji mnogo vrsta životinja i „životinja” je prilično širok pojam. Među vrstama životinja poznate su nam mačka (Cat), pas (Dog) i slične — sve imaju opšte osobine životinja (na primer mogu da jedu, mogu da proizvode zvuke), ali se u detaljima međusobno razlikuju (različite životinje jedu različitu hranu i imaju različite glasove).
Kada u Javi implementiramo klase kao što su Cat i Dog, potrebno je naslediti klasu Animal. Nakon nasleđivanja, konkretne klase životinja (Cat, Dog) postaju podklase, a klasa Animal roditeljska klasa.

02. Zašto nam je potrebno nasleđivanje
Sanmej, možda se pitate zašto nam je potrebno nasleđivanje?
Ako postoji samo dve-tri klase sa veoma ograničenim brojem osobina i metoda, zaista nema potrebe za nasleđivanjem. Ali stvari nisu tako jednostavne: u jednom sistemu često postoji mnogo klasa koje imaju mnogo zajedničkog — na primer mačka i pas su obe životinje, ili student i nastavnik su obe osobe. Pojedinačne klase mogu imati mnogo istih osobina i metoda, pa ako bi se svaka klasa pisala iznova, kod bi bio neuredan, a obim posla veliki.
Tu dolazi do izražaja prednost nasleđivanja: mogu se direktno koristiti osobine i metode roditeljske klase, a istovremeno se mogu dodati nove osobine i metode radi proširenja; ako je potrebno promeniti neku metodu roditeljske klase, ona se može redefinisati. Tako nasleđivanje ne samo da znatno smanjuje količinu koda, već i čini strukturu koda jasnijom i preglednijom.

Dakle, sa stanovišta koda, ovako bismo dizajnirali kompletnu klasu Animal:
class Animal
{
public int id;
public String name;
public int age;
public int weight;
public Animal(int id, String name, int age, int weight) {
this.id = id;
this.name = name;
this.age = age;
this.weight = weight;
}
//get i set metode su ovde izostavljene
public void sayHello()
{
System.out.println("hello");
}
public void eat()
{
System.out.println("I'm eating");
}
public void sing()
{
System.out.println("sing");
}
}A klase Dog, Cat i Chicken mogu se ovako dizajnirati:
class Dog extends Animal//nasleđuje Animal
{
public Dog(int id, String name, int age, int weight) {
super(id, name, age, weight);//poziva konstruktor roditeljske klase
}
}
class Cat extends Animal{
public Cat(int id, String name, int age, int weight) {
super(id, name, age, weight);//poziva konstruktor roditeljske klase
}
}
class Chicken extends Animal{
public Chicken(int id, String name, int age, int weight) {
super(id, name, age, weight);//poziva konstruktor roditeljske klase
}
//koka polaže jaja
public void layEggs()
{
System.out.println("Ja sam stara koka, snela sam jaje, kokodak! Kokodak!");
}
}Nakon što svaka klasa nasledi Animal, može direktno koristiti osobine i metode klase Animal bez ponovnog pisanja; a ako pojedinoj klasi zatreba sopstvena metoda, lako se može proširiti.
03. Podela nasleđivanja
Nasleđivanje se deli na jednostruko i višestruko; Java podržava samo jednostruko nasleđivanje klasa, ali se implementacijom interfejsa može postići cilj višestrukog nasleđivanja. O tome smo već govorili kada smo obrađivali interfejse, ali ovde ćemo kratko ponoviti.
| Nasleđivanje | Definicija | Prednosti i mane |
|---|---|---|
Jednostruko nasleđivanje![]() | Podklasa ima samo jednu roditeljsku klasu | Prednost: hijerarhija klasa je prilično jasna Mana: bogatstvo strukture ponekad ne zadovoljava potrebe |
Višestruko nasleđivanje (Java ga ne podržava, ali se drugim sredstvima može zadovoljiti) ![]() | Podklasa ima više neposrednih roditeljskih klasa | Prednost: bogatstvo podklase je veliko Mana: lako dovodi do zabune |
Jednostruko nasleđivanje
Jednostruko nasleđivanje — podklasa ima samo jednu roditeljsku klasu, kao što smo gore prikazali na primeru klase Animal i njenih podklasa. Jednostruko nasleđivanje daje jasnu hijerarhiju klasa, ali mu je mana što bogatstvo strukture ponekad ne zadovoljava potrebe.
Višestruko nasleđivanje
Višestruko nasleđivanje — podklasa ima više neposrednih roditeljskih klasa. Prednost je u tome što podklasa poseduje osobine svih roditeljskih klasa, pa je bogatstvo podklase veliko, ali je mana što lako dovodi do zabune. Sledeća slika prikazuje jedan konfuzni primer.

Iako Java ne podržava višestruko nasleđivanje, postoje tri načina da se ostvari njegov efekat: unutarnje klase, višeslojno nasleđivanje i implementacija interfejsa.
Unutrašnja klasa može naslediti klasu koja nije vezana za spoljašnju klasu, čime se čuva njena nezavisnost — i upravo na toj osnovi može se postići efekat višestrukog nasleđivanja.
Višeslojno nasleđivanje: podklasa nasleđuje roditeljsku klasu, a ako roditeljska klasa nadalje nasleđuje neku drugu klasu, to se naziva višeslojnim nasleđivanjem. Tada podklasa poseduje osobine i metode svih nasleđenih klasa.

Implementacija interfejsa nesumnjivo je najbolji način da se zadovolje potrebe višestrukog nasleđivanja — jedna klasa može implementirati više interfejsa i time zadovoljiti svoje potrebe u složenijim i bogatijim okruženjima.
U poređenju sa klasom, klasa je entitet koji ima osobine i metode, dok je interfejs pre skup metoda. Za primer, uzmimo Tang Sana iz „Borbenih hronika Douloa” — njegov odnos nasleđivanja mogao bi izgledati ovako:

04. Kako ostvariti nasleđivanje
Ključna reč extends
U Javi je nasleđivanje klasa jednostruko, odnosno podklasa može imati samo jednu roditeljsku klasu, pa extends može naslediti samo jednu klasu. Njena sintaksa glasi:
class ImePodklase extends ImeRoditeljskeKlase{}Na primer, klasa Dog nasleđuje klasu Animal, i to izgleda ovako:
class Animal{} //definicija klase Animal
class Dog extends Animal{} //klasa Dog nasleđuje klasu AnimalNakon što podklasa nasledi roditeljsku klasu, poseduje njene neprivatne osobine i metode. Ako ti to nije jasno, pogledajte sledeći slučaj: u IDEA-i kreirajte projekat, napravi test klasu za proveru, pa kreirajte klase Animal i Dog. Klasa Animal neka kao roditeljska ima metodu sayHello(), a klasa Dog nakon nasleđivanja klase Animal može pozvati metodu sayHello(). Konkretan kod je:
class Animal {
public void sayHello()//metoda roditeljske klase
{
System.out.println("hello,everybody");
}
}
class Dog extends Animal//nasleđuje Animal
{ }
public class test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.sayHello();
}
}Kada se klikne na pokretanje, podklasa Dog može direktno da koristi metode roditeljske klase Animal.

Ključna reč implements
Ključna reč implements može, takoreći indirektno, dati Javi osobine višestrukog nasleđivanja; koristi se kada klasa implementira interfejs, a jedna klasa može implementirati više interfejsa (interfejsi se razdvajaju zarezom).
Pogledajmo primer: kreirajmo test2 klasu za proveru, pa zatim interfejse doA i doB. Interfejs doA neka deklariše metodu sayHello(), interfejs doB metodu eat(). Kreirajmo klasu Cat2 koja implementira interfejse doA i doB, pri čemu je u klasi potrebno redefinisati metode sayHello() i eat(). Konkretan kod je:
interface doA{
void sayHello();
}
interface doB{
void eat();
//sledeća linija bi prijavila grešku: metoda u interfejsu ne može imati telo, samo deklaraciju
//public void eat(){System.out.println("eating");}
}
class Cat2 implements doA,doB{
@Override//mora se redefinisati metoda iz interfejsa
public void sayHello() {
System.out.println("hello!");
}
@Override
public void eat() {
System.out.println("I'm eating");
}
}
public class test2 {
public static void main(String[] args) {
Cat2 cat=new Cat2();
cat.sayHello();
cat.eat();
}
}Kada klasa Cat implementira interfejse doA i doB, potrebno je implementirati njihove deklarisane metode. Rezultat pokretanja je prikazan u slici ispod — to je jednostavan primer implementacije interfejsa u klasi:

05. Osobine nasleđivanja
Glavni sadržaj nasleđivanja svodi se na to da podklasa nasleđuje roditeljsku klasu i redefiniše njene metode. Pri korišćenju osobina ili metoda podklase prvo treba kreirati objekat, a objekat se kreira putem konstruktora. U konstruktoru možemo pozivati neke osobine i metode podklase odnosno roditeljske klase, zato je potrebno unapred savladati ključne reči this i super.
Nakon što se objekat kreira, pozivaju se metode redefinisane u odnosu na roditeljsku klasu; obrati pažnju na razliku između redefinisanja i preopterećenja.
Ključne reči this i super
Kasnije ćemo ih obraditi detaljno; ovde samo dajemo kratki uvod.
Ključne reči this i super veoma su važne u kontekstu nasleđivanja; označavaju redom referencu na trenutni objekat i referencu na objekat roditeljske klase. Veoma su slične, ali se i međusobno razlikuju.
this ukazuje na trenutni objekat — referenca je koja ukazuje sama na sebe.
this.osobina // pristup članskoj promenljivoj, da bi se razlikovale članska i lokalna promenljiva
this.() // poziv neke metode iste klase
this() // poziv konstruktora iste klasesuper ukazuje na objekat roditeljske klase — referenca je koja ukazuje na roditeljsku klasu.
super.osobina // članska promenljiva objekta roditeljske klase
super.metoda() // metoda definisana u objektu roditeljske klase
super() // poziv konstruktora roditeljske klaseKonstruktor
Konstruktor specijalna je vrsta metode, to je metoda koja nosi isto ime kao klasa. U nasleđivanju konstruktor je prilično specifična metoda (na primer ne može se naslediti), pa je potrebno razumeti pravila i zahteve koji se odnose na konstruktore u okviru nasleđivanja.
Pri nasleđivanju obratite pažnju na sledeće stavke vezane za konstruktor:
Konstruktor roditeljske klase ne može se naslediti:
Sintaksa konstruktora nalaže da on ima isto ime kao klasa, a nasleđivanje ne menja ime metode. Ako bi podklasa nasledila konstruktor roditeljske klase, to bi očigledno dovelo do sukoba sa sintaksom konstruktora. Na primer, konstruktor klase Father zove se Father(); ako klasa Son nasledi konstruktor Father() klase Father, to bi dovelo do sukoba sa definicijom da konstruktor ima isto ime kao klasa. Zato podklasa ne može naslediti konstruktor roditeljske klase, ali će je pozivati.
Proces konstrukcije podklase mora pozvati konstruktor svoje roditeljske klase:
Java virtuelna mašina pre konstrukcije objekta podklase prvo konstruiše objekat roditeljske klase, a tek nakon toga posebne osobine podklase — to se naziva memorijskim preklapanjem. Pošto Java virtuelna mašina pri konstrukciji objekta roditeljske klase izvršava njen konstruktor, konstruktor podklase mora pozvati super(), odnosno konstruktor roditeljske klase. Tako bi, na primer, jednostavan slučaj nasleđivanja trebalo da se napiše ovako:
class A{
public String name;
public A() {//konstruktor bez argumenata
}
public A (String name){//konstruktor sa argumentima
}
}
class B extends A{
public B() {//konstruktor bez argumenata
super();
}
public B(String name) {//konstruktor sa argumentima
//super();
super(name);
}
}Ako konstruktor podklase eksplicitno ne pozove konstruktor roditeljske klase, sistem podrazumevano poziva konstruktor roditeljske klase bez argumenata.
Ponekad pri pisanju nasleđivanja podklasa ne koristi super(), a program i dalje radi ispravno — to je zapravo radi uštede koda: sistem tokom izvršenja automatski dodaje poziv konstruktoru roditeljske klase bez argumenata. Ako ne verujete, malo izmenimo gornje klase i izvršimo:

Redefinisanje metode (Override)
Redefinisanje metode znači da se u podklasi pojavi metoda potpuno ista kao u roditeljskoj klasi (uključujući tip povratne vrednosti, ime metode i listu parametara); ona se temelji na nasleđivanju. Možete je zamisliti tako da spoljašnji oblik metode ostaje nepromenjen, ali se unutrašnji sadržaj piše iznova.
Evo jednog jednostavnog i razumljivog primera redefinisanja metode:
class E1{
public void doA(int a){
System.out.println("Ovo je metoda roditeljske klase");
}
}
class E2 extends E1{
@Override
public void doA(int a) {
System.out.println("Redefinišem metodu roditeljske klase, ovo je metoda podklase");
}
}Anotacija @Override eksplicitno označava da je reč o redefinisanoj metodi i može vam pomoći da proverite ispravnost sintakse redefinicije; naravno, može i bez nje, ali se preporučuje da se stavi.
Preopterećenje metode (Overload)
Ako dve metode imaju isto ime, ali različite parametre, onda se može reći da je jedna metoda preopterećenje druge.
Preopterećenje se obično može shvatiti kao situacija u kojoj metode koje obavljaju istu stvar imaju isto ime, ali različite liste parametara, a eventualno i druge razlike. Jednostavan primer preopterećenja — metoda add() u klasi E3 jeste preopterećena metoda.
class E3{
public int add(int a,int b){
return a+b;
}
public double add(double a,double b) {
return a+b;
}
public int add(int a,int b,int c) {
return a+b+c;
}
}06. Nasleđivanje i modifikatori
Uloga Java modifikatora jeste da modifikuju ili ograniče klasu ili njene članove; svaki modifikator ima svoju ulogu, a u nasleđivanju neki specijalni modifikatori mogu sprečiti nasleđivanje obeležene osobine ili metode, ili postaviti dodatne uslove za nasleđivanje.
Java nudi mnogo modifikatora; oni služe za definisanje klasa, metoda ili promenljivih i obično se nalaze na samom početku iskaza. Glavno se dele u dve kategorije:
- Modifikatori za kontrolu pristupa — public, private, protected itd.
- Modifikatori koji nisu vezani za pristup — static, final, abstract itd.
Modifikatori za kontrolu pristupa
Kada Java podklasa redefiniše nasleđenu metodu, ne sme joj smanjiti nivo pristupa; opseg modifikatora pristupa koji podklasa nasleđuje ne može biti uži od onog u roditeljskoj klasi, odnosno mora biti otvoreniji. Ako je u roditeljskoj klasi metod obeležen sa protected, u podklazi sme biti samo protected ili public, a nikako default (podrazumevani opseg pristupa) ili private. Zato metode koje se u nasleđivanju redefinišu ne mogu biti obeležene sa private.
Ako ti i dalje nije jasno, nekoliko malih primera će brzo razjasniti stvari. Napiši klasu A1 sa četiri metode obeležena sa četiri različita modifikatora, a zatim neka podklasa A2 nasledi A1; prilikom redefinicije metoda klase A1 primetićete da se privatna metoda roditeljske klase ne može redefinisati, a da se opseg modifikatora pristupa ne sme suziti pri redefiniciji neproprivatnih metoda (mora biti veći ili jednak).

Pravilan primer bi trebalo da izgleda ovako:
class A1 {
private void doA(){ }
void doB(){}//default
protected void doC(){}
public void doD(){}
}
class A2 extends A1{
@Override
public void doB() { }//opseg modifikatora pristupa može se proširiti pri redefiniciji u podklasi
@Override
protected void doC() { }//opseg modifikatora pristupa može ostati isti kao u roditeljskoj klasi
@Override
public void doD() { }//ne sme biti protected ili default
}Takođe treba imati na umu da u nasleđivanju izuzetke koje baca podklasa moraju biti jednaki izuzecima koje baca roditeljska klasa ili podizuzetci tih izuzetaka. Sledeći primer sa četiri metode pokazuje da opseg izuzetaka metode podklase ne sme biti veći od opsega izuzetaka odgovarajuće metode roditeljske klase.

Pravilan primer bi trebalo da izgleda ovako:
class B1{
public void doA() throws Exception{}
public void doB() throws Exception{}
public void doC() throws IOException{}
public void doD() throws IOException{}
}
class B2 extends B1{
//opseg izuzetka može biti isti kao u roditeljskoj klasi
@Override
public void doA() throws Exception { }
//opseg izuzetka može biti uži nego u roditeljskoj klasi
@Override
public void doB() throws IOException { }
//opseg izuzetka ne sme biti veći od opsega u roditeljskoj klasi
@Override
public void doC() throws IOException { }//ne sme bacati Exception niti bilo koji izuzetak veći od IOException
@Override
public void doD() throws IOException { }
}Modifikatori koji nisu vezani za pristup
Modifikatori za kontrolu pristupa služe za upravljanje pravima pristupa, dok svaki od ostalih modifikatora ima svoju posebnu ulogu; u nastavku su objašnjeni modifikatori static, final i abstract.
static se prevodi kao „statički” i može se koristiti uz promenljive, metode i klase — tada govorimo o statičkim promenljivama i statičkim metodama (poznatim i kao promenljive klase, odnosno metode klase). Ako se u nekoj klasi modifikator static koristi za obeležavanje promenljive ili metode, može im se pristupiti direktno preko klase, bez kreiranja objekta te klase.
Pri dizajniranju klasa možemo koristiti statičke metode; mnoge korisne klase poput Math, Arrays i sličnih sadrže brojne statičke metode.
Primer koji dokazuje gornja pravila:

Izvorni kod je:
class C1{
public int a;
public C1(){}
// public static C1(){}// konstruktor ne sme biti deklarisan kao static
public static void doA() {}
public static void doB() {}
}
class C2 extends C1{
public static void doC()//u statičkoj metodi ne postoji trenutni objekat, pa se ne mogu koristiti this i super.
{
//System.out.println(super.a);
}
public static void doA(){}//statička metoda može se redefinisati statičkom metodom
// public void doB(){}//statička metoda ne može se redefinisati nestatičkom metodom
}final promenljive:
- final nosi značenje „krajnji, konačni” — jednom kada se promenljivoj dodeli vrednost, ona se ne može ponovo dodeliti. Instancna promenljiva obeležena sa final mora imati eksplicitno zadatu početnu vrednost (odnosno ne može se samo deklarisati). Modifikator final najčešće se koristi zajedno sa modifikatorom static radi kreiranja konstante klase.
final metode:
- final metode roditeljske klase mogu se naslediti u podklasi, ali se ne mogu redefinisati. Glavni razlog za deklarisanje final metode jeste sprečavanje izmene njenog sadržaja.
final klase:
- final klase ne mogu se nasleđivati — nijedna klasa ne može naslediti bilo koju osobinu final klase.
Dakle, kada se final nađe uz promenljivu, metodu ili klasu, uvek nosi značenje „konačno” — sadržaj se ne može izmeniti.
abstract na engleskom znači „apstraktan” i uglavnom se koristi za obeležavanje klasa i metoda, pa govorimo o apstraktnim klasama i apstraktnim metodama.
Apstraktna metoda: mnogo metoda u različitim klasama je slično, ali im se konkretan sadržaj razlikuje, pa možemo izdvojiti samo njihovu deklaraciju bez konkretnog tela metode; drugim rečima, apstraktna metoda može izraziti pojam, ali ne i konkretnu implementaciju.
Apstraktna klasa: klasa koja ima apstraktnu metodu mora biti apstraktna klasa; apstraktna klasa može izraziti pojam, ali se od nje ne može konstruisati entitet.

Na primer, možemo ovako dizajnirati apstraktnu klasu People i jednu apstraktnu metodu, a zatim je konkretno implementirati u podklasama:
abstract class People{
public abstract void sayHello();//apstraktna metoda
}
class Chinese extends People{
@Override
public void sayHello() {//implementacija apstraktne metode
System.out.println("Zdravo");
}
}
class Japanese extends People{
@Override
public void sayHello() {//implementacija apstraktne metode
System.out.println("Koniči va");
}
}
class American extends People{
@Override
public void sayHello() {//implementacija apstraktne metode
System.out.println("hello");
}
}07. Klasa Object i kastovanje tipova
Kada se govori o Java nasleđivanju, mora se spomenuti korenska klasa svih klasa — Object (java.lang.Object). Ako klasa ne deklariše svoju roditeljsku klasu (odnosno ne piše extends xx), onda se podrazumeva da joj je roditeljska klasa Object. Svaka klasa može koristiti metode klase Object, a kreirane klase mogu se kastovati nagore i nadole u odnosu na Object, pa je zato klasa Object obavezno znanje za razumevanje nasleđivanja.
Java kastovanje nagore i nadole često se koristi i takođe se temelji na nasleđivanju, pa je i to znanje neophodno za potpuno razumevanje nasleđivanja.
Pregled klase Object
- Object je korenska klasa hijerarhije klasa — sve klase implicitno nasleđuju klasu Object.
- U Javi svi objekti poseduju podrazumevane metode klase Object.
- Klasa Object ima konstruktor, i to konstruktor bez argumenata.
Object je roditeljska klasa svih Java klasa, na samom vrhu strukture nasleđivanja klasa, a ujedno i najapstraktnija klasa.
Metode poput toString(), equals(), hashCode(), wait(), notify(), getClass() i slične jesu metode klase Object. Ubuduće ćete se sa njima često sretati, a najviše sa toString() i equals(), jer ih često redefinišemo kako bismo zadovoljili svoje potrebe.
Metoda toString() vraća znakovnu reprezentaciju objekta; pošto se objekti različito konstruišu, potrebno ju je redefinisati. Ako se ne redefiniše, podrazumevano vraća format imeKlase@hashCode.
Ako se toString() redefiniše, njen direktn poziv može vratiti naš prilagođeni sadržaj klase pretvorene u znakove, bez ručnog spajanja sadržaja u string pri svakom ispisu, čime se izlazne operacije znatno pojednostavljuju.
Metoda equals() prvenstveno poredi dva objekta na jednakost; s obzirom na to da jednakost objekata ne mora nužno da znači striktnu jednakost adresa, ponekad nam je dovoljna jednakost sadržaja. Na primer, klasa String redefinisala je metodu equals() radi poređenja jednakosti po sadržaju znakova.

Kastovanje nagore (upcast)
Kastovanje nagore: instanciranje objekta roditeljske klase (širi opseg) putem objekta podklase (uži opseg) — to spada u automatsku konverziju. Jedna slika jasno prikazuje logiku kastovanja nagore:

Nakon što referentna promenljiva roditeljske klase ukazuje na objekat podklase, mogu se pozivati samo metode deklarisane u roditeljskoj klasi; ali ako je metoda redefinisana, izvršiće se metoda podklase, a ako nije, izvršiće se metoda roditeljske klase.
Kastovanje nadole (downcast)
Kastovanje nadole: instanciranje objekta podklase (uži opseg) putem objekta roditeljske klase (širi opseg); u kodu referentnu promenljivu roditeljske klase treba u zagradama () eksplicitno kastovati u tip podklase. Međutim, objekat na koji referentna promenljiva roditeljske klase stvarno ukazuje mora biti objekat podklase da bi konverzija uspela. I ovde jedna slika jasno prikazuje logiku kastovanja nadole:

Kada referentna promenljiva podklase počne da ukazuje na objekat na koji ukazuje referentna promenljiva roditeljske klase (jedan objekat Son()), kastovanje nadole je završeno i mogu se pozivati metode svojstvene podklasi, a ih roditeljska klasa nema.
Evo primera i za kastovanje nagore i za kastovanje nadole:
Object object=new Integer(666);//kastovanje nagore
Integer i=(Integer)object;//kastovanje nadole Object->Integer, object i dalje suštinski ukazuje na Integer
String str=(String)object;//pogrešno kastovanje nadole — kompajler neće prijaviti grešku, ali će se greška pojaviti pri izvršenju08. Redosled inicijalizacije roditeljske i podklase
U Java nasleđivanju, redosled inicijalizacije roditeljske i podklase je:
- Statičke članice i statički blokovi koda u roditeljskoj klasi
- Statičke članice i statički blokovi koda u podklasi
- Obične članice i blokovi koda u roditeljskoj klasi, pa konstruktor roditeljske klase
- Obične članice i blokovi koda u podklasi, pa konstruktor podklase
Ukratko: statičko pre nestatičkog, roditeljska klasa pre podklase, a ne-konstruktor pre konstruktora. Unutar iste kategorije (na primer obične promenljive i obični blokovi koda) članice i blokovi izvršavaju se redom od napred ka nazad, pri čemu treba obratiti pažnju na logiku.
Ni to nije teško razumeti: statičke promenljive poznate su i kao promenljive klase i mogu se posmatrati kao globalne promenljive; statičke članice i statički blokovi koda inicijalizuju se pri učitavanju klase, dok se nestatičke promenljive i blokovi koda inicijalizuju pri kreiranju objekta. Zato statička inicijalizacija prethodi nestatičkoj.
Pri kreiranju objekta podklase prvo se kreira objekat roditeljske klase, pa je roditeljska klasa ispred podklase.
Pri pozivu konstruktora izvršavaju se neke operacije inicijalizacije članica, pa obične članice i blokovi koda prethode konstruktoru.
Za dublje razumevanje ovog redosleda potrebno je bolje upoznati tok izvršenja JVM-a. Sledeći probni kod je:
class Father{
public Father() {
System.out.println(++b1+"Konstruktor roditeljske klase");
}//konstruktor roditeljske klase, četvrto
static int a1=0;//static roditeljske klase, prvo; obratite pažnju na redosled
static {
System.out.println(++a1+"static roditeljske klase");
}
int b1=a1;//članske promenljive i blokovi koda roditeljske klase, treće
{
System.out.println(++b1+"Blok koda roditeljske klase");
}
}
class Son extends Father{
public Son() {
System.out.println(++b2+"Konstruktor podklase");
}//konstruktor podklase, šesto
static {//static podklase, drugo
System.out.println(++a1+"static podklase");
}
int b2=b1;//članske promenljive i blokovi koda podklase, peto
{
System.out.println(++b2 + "Blok koda podklase");
}
}
public class test9 {
public static void main(String[] args) {
Son son=new Son();
}
}Rezultat izvršenja:

09. Zaključak
Dakle, Sanmej, toliko o nasleđivanju za ovaj put — savladala ste jednu od tri glavne odlike Java objektno orijentisanog programiranja.
Enkapsulacija: podrazumeva enkapsulaciju klase — enkapsulaciju njenih osobina i metoda, uz izlaganje samo metoda, bez izlaganja konkretnih detalja korišćenja. Zato članske promenljive klase najčešće postavljamo kao privatne, a čitanje i pisanje obavljamo preko get i set metoda.
Nasleđivanje: podklasa nasleđuje roditeljsku klasu — „dete nasleđuje očevinu“. Podklasa poseduje sve osobine i metode roditeljske klase, osim privatnih, i može na toj osnovi dodavati nove. Glavni cilj jeste ponovno iskorišćavanje koda.
Polimorfizam: polimorfizam je sposobnost istog ponašanja da ima više različitih oblika ili manifestacija. Drugim rečima, jedna roditeljska klasa može imati više podklasa, a svaka implementira metode roditeljske klase na svoj način; pri pozivu metode roditeljske klase, referentna promenljiva roditeljske klase ukazuje na različite instance podklasa i izvršavaju se različite metode — upravo to znači da je metoda roditeljske klase polimorfna.
Na kraju poklanjam ti jednu sliku da u njoj razvedete te odnose.

„Dobro, Autor, da svarim to; zaista je bilo mnogo sadržaja danas. Ti idi malo da se odmorite", odgovorila je Sanmej.
Referentni link: https://bbs.huaweicloud.com/blogs/271358, autor: bigsai, obrada: Marko Marković


