Osnovni principi OOP su:
Nasleđivanje (inheritance) je mogućnost uvođenja novih tipova/klasa proširivanjem osobina i ponašanja postojećih tipova/klasa.
Klasa koja nasleđuje (proširuje) se naziva IZVEDENA, POTKLASA ili DETE-KLASA i predstavlja uži tip podatka u odnosu na klasu iz koje je izvedena.
Klasa koja biva proširena, tj. čije osobine i ponašanja nasleđuje dete-klasa se naziva SUPERKLASOM, NATKLASOM ili RODITELJSKOM KLASOM i predstavlja širi tip podatka u odnosu na klasu iz koje je izvedena.
Svaka klasa može da ima neograničen broj potklasa. Potklase nisu ograničene na promenljive, konstruktore i metode klase koje nasleđuju od svoje roditeljske klase. Potklase mogu dodati i neke druge promenljive i metode ili predefinisati stare metode. U deklaraciji potklase navode se razlike između nje i njene superklase. Jedna klasa može da nasledi samo jednu klasu. Ako nije eksplicitno navedeno koju klasu nasleđuje neka klasa, onda nasleđuje klasu Object. Sve klase (i sistemske i naše) u Javi su direktno ili indirektno izvedene iz klase Object.
Primer 3.1
class B extends A {
//telo klase B
}
Koristeći klauzulu extends
klasa B nasleđuje klasu A.
Primer 3.2
Klase Student i Professor nasleđuju klasu Person. Klasa Person nasleđuje klasu Object.
Kada se kreira objekat, njegovi atributi se postavljaju na podrazumevanu vrednost: 0 (numerički), false (boolean), null (referenca). Nakon inicijalizacije se poziva konstrukor i to tako što se prvo izvršava kostruktor super klase, pa zatim telo konstruktora klase kojoj objekat koji se kreira pripada. Izvedena klasa mora da pozove jedan od konstruktora svoje super klase.
Eksplicitan poziv konstruktora super klase:
super(argumenti)
Ako se konstruktor ekplicitno poziva, taj poziv mora biti prva komanda u konstruktoru izvedene klase.
Ako se ne poziva eksplicitno, implicitno će biti pozvan default konstruktor natklase.
super() – eksplicitan poziv default konstruktora natklase.
Ukoliko ne postoji default-ni konstruktor, u konstruktoru izvedene klase se eksplicitno mora pozvati konstruktor roditeljske klase.
Ukoliko se u potklasi definiše metoda sa istim imenom, povratnom vrednošću i argumentima kao i metoda superklase tada se ovom metodom prepisuje (override) metoda superklase.
Za pristup originalnim metodama osnovne klase se koristi super.
Primer 3.3
class A {
void metodaA() {
System.out.println("A");
}
}
class B extends A {
void metodaA() {
super.metodaA();
System.out.println("B");
/* Ocekivani rezultat:
A
B
*/
}
}
final modifikator može biti primenjen na klase, varijable i metode. Uopšteno, povlači za sobom tvrdnju da je definicija elementa na koji se primenjuje konačna.
final varijabla – varijabla predstavlja konstantu i ne menja vrednost. Inicijalizacija ne mora da bude obavljena na mestu gde je konstanta deklarisana, ali je vrednost moguće samo jednom postaviti.
final klasa – definicija tipa je konačna, pa klasa ne može biti proširena, tj. ne može biti nasleđena.
final metod – ne može biti prepisan (overrided).
Final može da bude i argument metoda i tada se ta varijabla ne može menjati unutar metoda.
Reč “polimorfizam” potiče od grčkih reči “poly” što znači “mnogo” i “morphē” što znači “oblik” ili “formu”.
Polimorfizam je mogućnost da varijablom određenog tipa referenciramo objekte različitih tipova i da automatski pozivamo metode koje su specifične za tip objekta na koji varijabla referencira.
Uslovi:
Ako imamo promenljivu tipa K, gde je K klasa možemo joj dodeliti sledeće vredosti:
Nadtipovi su manje posebni, smatraju se širim i nalaze se više u hijerahiji tipova.
Konverzija proširivanja (naviše, nagore)
Konverzija sužavanja (naniže, nadole)
Primer 3.4
class Student extends Gradjanin { … }
…
Sudent s = new Sudent();
Gradjanin g = new Gradjanin();
Gradjanin g2 = s; // naviše
Sudent s1 = (Sudent) g; // naniže, obavezan cast
Klasa dete ne može da prepiše static metodu roditeljske klase već samo da je “sakrije”, tj. da napiše svoju implementaciju te metode.
Unutar static metoda se ne može koristiti super.
Primer 3.5
class A {
void nestatickaMetoda() {
System.out.println("A");
}
static void statickaMetoda() {
System.out.println("static A");
}
}
class B extends A {
void nestatickaMetoda() {
System.out.println("B");
}
static void statickaMetoda() {
System.out.println("static B");
}
}
class Test {
public static void main(String[] args) {
A objekat = new B();
a.nestatickaMetoda(); // ispisuje "B"
a.statickaMetoda(); // ispisuje "static A"
}
}
Polimofizam ne važi kod statičkih metoda i treba izbegavati pozive statičkih metoda koristeći objekat (objekat.statickaMetoda()). Bolja praksa je korišćenje naziva klase za pozivanje statičkih metoda (A.statickaMetoda() ili B.statickaMetoda()).