11 pravila koja treba poštovati pri prepisivanju (Overriding) u Javi
Prepisivanje (Overriding) je vrlo važan koncept u Javi, razumevanje šta je prepisivanje vrlo je važno za svakog Java programera, ovaj članak će vam reći koja pravila treba poštovati pri prepisivanju.
01, Što je prepisivanje?
Prepisivanje donosi vrlo važnu sposobnost, omogućava podklasi da ponovo implementira metodu nasleđenu iz superklase. U sledećoj slici, Animal je nadklasa, Dog je podklasa, Dog ponovo implementira move() metodu za razlikovanje od nadklase, budući da psi ipak imaju poseban način trčanja.

Prepisana metoda i prepisivana metoda ne samo da isto ime, već su isti parametri, samo je telo metode drugačije.
02, Koje metode mogu biti prepisane?
Pravilo jedno: Mogu se prepisati samo nasleđene metode.
Budući da se prepisivanje dešava kada podklasa ponovo implementira metodu nasleđenu iz nadklase, mogu se prepisati samo nasleđene metode, ovo je lako razumeti. To znači da se mogu prepisati samo metode modifikovane sa public, protected ili default, metode modifikovane sa private ne mogu se prepisati.
Animal klasa ima tri metode move(), eat() i sleep():
public class Animal {
public void move() { }
protected void eat() { }
void sleep(){ }
}Dog klasa prepisuje ove tri metode:
public class Dog extends Animal {
public void move() { }
protected void eat() { }
void sleep(){ }
}OK, potpuno bez problema. Ali ako je metoda u nadklasi private, neće proći.
public class Animal {
private void move() { }
}U ovom trenutku, move() metoda u Dog klasi više nije prepisana metoda, budući da je move() metoda u nadklasi private, za podklasu nije vidljiva.
public class Dog extends Animal {
public void move() { }
}03, Koje metode ne mogu biti prepisane?
Pravilo dva: final, static metode ne mogu se prepisati.
Ako je metoda final, to znači da ne može biti nasleđena u podklasu, stoga se ne može prepisati.
public class Animal {
final void move() { }
}Budući da je move() u Animal nadklasi final, kada podklasa pokuša da prepise tu metodu, dolazi do greške pri kompajliranju!

Slično, ako je metoda static, takođe nije dozvoljeno prepisivanje, budući da statičke metode mogu koristiti sve instance nadklase i podklase.
public class Animal {
final void move() { }
}Svrha prepisivanja je pokazivanje polimorfizma na osnovu različitih tipova objekata, dok statičke metode ne zahtevaju kreiranje objekata za korišćenje. Bez objekata, „tip objekta“ potreban za prepisivanje nema smisla.

04, Zahtevi za prepisivanje metoda
Pravilo tri: Prepisana metoda mora imati istu listu parametara.
public class Animal {
void eat(String food) { }
}eat() metoda u Dog klasi održava isti melos kao metoda eat() nadklase, ima jedan parametar — tip String za food.
public class Dog extends Animal {
public void eat(String food) { }
}Jednom kada podklasa ne prati ovo pravilo, na primer ako doda jedan parametar:
public class Dog extends Animal {
public void eat(String food, int amount) { }
}Ovo više nije pitanje prepisivanja, naravno nije ni preopterećenje (overloading), budući da se preopterećenje bavi istom klasom.
Pravilo četiri: Prepisana metoda mora vratiti isti tip.
Nadklasa nema povratni tip:
public class Animal {
void eat(String food) { }
}Podklasa pokušava da vrati String:
public class Dog extends Animal {
public String eat(String food) {
return null;
}
}Dolazi do greške pri kompajliranju (nekompatibilni povratni tipovi).

Pravilo pet: Prepisana metoda ne može koristiti modifikatore pristupa strože ograničenog nivoa.
Možete razumeti na sledeći način:
- Ako je prepisivana metoda default, onda prepisana metoda može biti default, protected ili public.
- Ako je prepisivana metoda protected, onda prepisana metoda može biti samo protected ili public.
- Ako je prepisivana metoda public, onda prepisana metoda može biti samo public.
Na primer, metoda u nadklasi je protected:
public class Animal {
protected void eat() { }
}Metoda u podklasi može biti public:
public class Dog extends Animal {
public void eat() { }
}Ako metoda u podklasi koristi modifikator pristupa strože ograničenog nivoa, kompajler će prijaviti grešku.

Pravilo šest: Prepisana metoda ne može baciti višeg nivoa izuzetak nego u nadklasi.
Na primer, ako metoda u nadklasi baca IOException, onda prepisana metoda u podklasi ne može baciti Exception, može biti podklasa IOException ili ne bacati nijedan izuzetak. Ovo pravilo se odnosi samo na proverljive (checked) izuzetke.
Proverljivi (checked) izuzetci moraju biti eksplicitno uhvaćeni i obrađeni u izvornom kodu, neproverljivi (unchecked) izuzetci su takozvani runtime izuzeci, na primer NullPointerException, ArrayIndexOutOfBoundsException itd., kompajler ih neće nužno zahtevati.
Nadklasa baca IOException:
public class Animal {
protected void eat() throws IOException { }
}Podklasa koja baca FileNotFoundException može zadovoljiti pravila prepisivanja, budući da je FileNotFoundException podklasa IOException.
public class Dog extends Animal {
public void eat() throws FileNotFoundException { }
}Ako podklasa baca novi izuzetak, i to je checked izuzetak:
public class Dog extends Animal {
public void eat() throws FileNotFoundException, InterruptedException { }
}Onda će kompajler prijaviti grešku:
Error:(9, 16) java: com.itwanger.overriding.Dog.eat() ne može pokriti com.itwanger.overriding.Animal.eat()
Preklopljena metoda ne baca java.lang.InterruptedExceptionAli ako podklasa baca unchecked izuzetak, onda nema konflikta:
public class Dog extends Animal {
public void eat() throws FileNotFoundException, IllegalArgumentException { }
}Ako podklasa baca izuzetak višeg nivoa:
public class Dog extends Animal {
public void eat() throws Exception { }
}Kompajler će takođe prijaviti grešku, budući da je Exception nadklasa IOException.
Error:(9, 16) java: com.itwanger.overriding.Dog.eat() ne može pokriti com.itwanger.overriding.Animal.eat()
Preklopljena metoda ne baca java.lang.Exception05, Kako pozvati prepisanu metodu?
Pravilo sedam: U podklasi se može pozvati prepisana metoda nadklase kroz super ključnu reč.
Vrlo je čest praksu da podklasa nasleđuje metodu nadklase umesto da je ponovo implementira, u ovom slučaju, možete pozvati metodu nadklase u sledećem obliku:
super.overriddenMethodName();Pogledajmo primer.
public class Animal {
protected void eat() { }
}Podklasa je prepisala eat() metodu, onda u eat() metodi podklase, u prvom redu tela metode možete pozvati metodu nadklase kroz super.eat(), zatim dodati kod koji pripada vama.
public class Dog extends Animal {
public void eat() {
super.eat();
// Dog-eat
}
}06, Prepisivanje i konstruktorske metode
Pravilo osam: Konstruktorske metode ne mogu se prepisati.
Budući da su konstruktorske metode vrlo specifične, i konstruktorska metoda podklase ne može imati isto ime kao konstruktorska metoda nadklase (različita imena klasa), stego ne postoji nikakva veza između konstruktorskih metoda i prepisivanja.
07, Prepisivanje i apstraktne metode
Pravilo devet: Ako klasa nasleđuje apstraktnu klasu, apstraktne metode u apstraktnoj klasi moraju biti prepisane u podklasi.
Prvo pogledajmo ovakvu interfejs klasu:
public interface Animal {
void move();
}Metode u interfejsu su podrazumevano apstraktne, može se videti kroz dekompajliranje:
public interface Animal
{
public abstract void move();
}Ako apstraktna klasa implementira Animal interfejs, move() metoda ne mora biti prepisana:
public abstract class AbstractDog implements Animal {
protected abstract void bark();
}Ali ako klasa nasleđuje apstraktnu klasu AbstractDog, onda move() metoda iz Animal interfejsa i apstraktna metoda bark() iz apstraktne klase AbstractDog moraju biti prepisane:
public class BullDog extends AbstractDog {
public void move() {}
protected void bark() {}
}08, Prepisivanje i synchronized metode
Pravilo deset: synchronized ključna reč nema nikakav uticaj na pravila prepisivanja.
synchronized ključna reč se koristi u multithread okruženju za dobavljanje i otpuštanje objekta monitoringa, stego nema nikakav uticaj na pravila prepisivanja, to znači da synchronized metoda može prepisati nesinhronizovanu metodu.
09, Prepisivanje i strictfp metode
Pravilo jedanaest: strictfp ključna reč nema nikakav uticaj na pravila prepisivanja.
Ako želite da operacije sa pokretnim zarezom budu preciznije, i neće dovesti do nekonzistentnih rezultata zbog različitih hardverskih platformi, možete dodati strictfp ključnu reč na metodu. Stego strictfp ključ i pravila prepisivanja su nepovezani.
