Overriding / Suprascriere
Suprascrierea este mecanismul de rescriere a unei metode într-o clasă derivată. Acest lucru ne permite să definim o implementare mai specializată pentru clasa respectivă.
Beneficiile suprascrierii includ: abilitatea de a defini un comportament specific subclasei, ceea ce înseamnă că subclasa poate implementa metodele super-clasei în funcţie de cerinţele specifice ale acesteia. În termeni OOP, suprascrierea înseamna să redefinim funcţionalitatea unei metode existente.
class Animal { public void move() { System.out.println("Animals can move"); } }
class Dog extends Animal { public void move(){ System.out.println("Dogs can walk and run"); } public void bark(){ System.out.println("Dogs can bark"); } }
public class TestDog { public static void main(String args[]) { Animal a = new Animal(); // Animal reference and object Animal b = new Dog(); // Animal reference but Dog object a.move(); // runs the method in Animal class b.move(); //runs the method in Dog class } }
Codul de mai sus va produce următorul rezultat:
Animals can move Dogs can walk and run
În exemplul de mai sus, putem observa că obiectul b
, chiar dacă este de tipul Animal apelează metoda din clasa Dog. Motivul este următorul: la compilare, verificarea este făcută pe tipul referinţei. Cu toate acestea, la rulare, JVM rulează metoda care aparţine tipului instanţiat. Aşadar, în exemplul de mai sus, programul se va compila corect, clasa Animal având metoda move()
. Apoi, la rulare se va executa metoda specifică clasei Dog.
Mai este un amănunt de care trebuie să ţinem seama. Avem următorul exemplu:
public class TestDog { public static void main(String args[]){ Animal a = new Animal(); // Animal reference and object Animal b = new Dog(); // Animal reference but Dog object a.move(); // runs the method in Animal class b.move(); //runs the method in Dog class b.bark(); } }
Codul de mai sus va produce următorul rezultat:
TestDog.java:30: cannot find symbol symbol : method bark() location:class Animal b.bark(); ^
Acest program va arunca o eroare de compilare, deoarece variabila b
este de tipul Animal, care nu are nicio metodă bark()
.
Reguli pentru suprascrierea metodelor
- Lista argumentelor ar trebui să fie exact la fel ca şi lista din metoda suprascrisă.
- Tipul returnat ar trebui să fie la fel sau un subtip a tipului declarat în metoda originală din superclasă.
- Nivelul de acces nu poate fi mai restrictiv decât nivelul de acces al metodei suprascrise. De exemplu, dacă metodele din superclasă sunt declarate public, atunci metoda din subclasă nu poate fi declarată nici private nici protected.
- Metodele de instanţă pot fi suprascrise doar dacă sunt moştenite de subclasă.
- O metodă declarată final nu poate fi suprascrisă.
- O metodă declarată static nu poate fi suprascrisă, dar poate fi re-declarată.
- Dacă o metodă nu poate fi moştenită, atunci nu poate fi suprascrisă.
- O subclasă din acelaşi pachet ca şi clasa de bază poate suprascrie orice metodă care nu este declarată private sau final.
- O subclasă dintr-un pachet diferit poate declara doar metodele non-final care sunt declarate public sau protected.
- Constructorii nu pot fi suprascrişi.
Assignment
Realizaţi următoarea ierarhie de clase: porniţi de o clasă Om, care are 3 atribute (nume, vârstă, sex), care va fi extinsă de 2 clase (Cursant şi Angajat), care să aibă fiecare un atribut propriu. Acestea vor fi extinse la rândul lor de alte clase, fiecare cu câte un atribut propriu: Cursant de Elev şi Student, iar Angajat de Programator, Contabil, Trainer. Afişaţi-le atributele. Folosiţi şi metoda toString().
Om | ||||||
---|---|---|---|---|---|---|
String nume int varsta char sex |
||||||
Cursant | Angajat | |||||
String institutie | int salariu | |||||
Elev | Student | Programator | Contabil | Trainer | ||
String clasa | int anStudiu | String limbaj | boolean isSenior | int nrCursanti |