15. Polimorfizam /POLYMORPHISM/

Polimorfizam u Javi je koncept pomoću kojeg možemo izvesti jednu akciju na različite načine. Riječ polimorfizam se izvodi iz dve grčke riječi: poly i morphe. Riječ "poly" znači više, a "morphe" znači oblik. Dakle, polimorfizam znači više oblika. Postoje dva tipa polimorfizma u Javi: polimorfizam u vremenu kompajliranja i polimorfizam u vremenu izvršavanja. Polimorfizam u Javi se može izvoditi pomoću preopterećenja metode i preklapanja metode. Ako se preoptereti statička metoda u Javi, to je primjer polimorfizma u vremenu kompajliranja. Ovdje ćemo se fokusirati na polimorfizam u vremenu izvršavanja. Polimorfizam u vremenu izvršavanja Polimorfizam u vremenu izvršavanja (runtime polymorphism) ili dinamičko otpremanje metode (Dynamic Method Dispatch) je proces u kojem se poziv preklopljene metode rješava u vremenu izvršavanja, a ne u vremenu kompajliranja. U ovom procesu, preklopljena metoda se poziva preko referentne varijable superklase. Određivanje koja će metoda biti pozvana se zasniva na objektu na koji ukazuje referentna varijabla. Prije runtime polimorfizma treba shvatiti pojam podizanja (upcasting). Upcasting Kada referentna varijabla roditeljske klase upućuje na objekt klase-djeteta, to je poznato kao upcasting. Na primjer:

    class A{}  
    class B extends A{}  

    A a=new B(); //upcasting

Primjer 1 Java runtime polimorfizma U ovom primjeru, kreiraćemo dve klase Bike i Splender. Splender klasa nasljeđuje Bike klasu i preklapa njenu run() metodu. Metodu run pozivamo pomoću referentne varijable roditeljske klase. Pošto ona upućuje na objekt podklase, a metoda podklase preklapa metodu roditeljske klase, metoda podklase se poziva u vremenu izvršavanja. Pošto pozivanje metode određuje JVM a ne kompajler, to je poznato kao runtime polimorfizam.

class Bike{  
  void run(){System.out.println("vozi");}  
}  
class Splender extends Bike{  
  void run(){System.out.println("vozi sigurno 60km/h");}  
  
  public static void main(String args[]){  
    Bike b = new Splender(); //upcasting  
    b.run();  
  }  
} 

Ispis na ekranu:
vozi sigurno 60km/h.

Primjer 2 Java runtime polimorfizma Razmotrimo sljedeći scenario: Bank je klasa koja obezbjeđuje metodu za dobijanje kamatne stope. Ali, kamatna stopa se može razlikovati u zavisnosti od banke. Na primjer, banke ABC, DEF i GHI mogu davati kamatnu stopu od 8%, 7% i 9%.

Napomena: Ovo je takođe dato u preklapanju metoda ali tamo nije bilo upcastinga.

class Bank{  
int getRateOfInterest(){return 0;}  
}  
  
class ABC extends Bank{  
int getRateOfInterest(){return 8;}  
}  
  
class DEF extends Bank{  
  int getRateOfInterest(){return 7;}  
}  
class GHI extends Bank{  
  int getRateOfInterest(){return 9;}  
}  
  
class Test3{  
  public static void main(String args[]){  
    Bank b1=new ABC();  
    Bank b2=new DEF();  
    Bank b3=new GHI();  
    System.out.println("ABC kamatna stopa: "+b1.getRateOfInterest());  
    System.out.println("DEF kamatna stopa: "+b2.getRateOfInterest());  
    System.out.println("GHI kamatna stopa: "+b3.getRateOfInterest());  
  }  
}

Ispis na ekranu:
ABC kamatna stopa: 8
DEF kamatna stopa: 7
GHI kamatna stopa: 9

Java runtime polimorfizam sa podatkom-članom Preklopljena je metoda, a ne podaci-članovi, tako da runtime polimorfizam ne može biti postignut pomoću podataka-članova. U sljedećem primjeru, obe klase imaju podatak-član speedlimit, podatku-članu pristupamo pomoću referentne varijable roditeljske klase koja upućuje na objekt podklase. Pošto pristupamo podatku-članu koji nije preklopljen, to će značiti da će se uvijek pristupiti podatku-članu roditeljske klase. Pravilo: Runtime polimorfizam se ne može postići pomoću podataka-članova.

class Bike{  
 int speedlimit=90;  
}  
class Honda3 extends Bike{  
 int speedlimit=150;  
  
 public static void main(String args[]){  
   Bike obj=new Honda3();  
   System.out.println(obj.speedlimit); //90  
}

Ispis na ekranu:
90

Java runtime polimorfizam sa višenivoskim (multilevel) nasljeđivanjem Pogledajmo jednostavan primjer runtime polimorfizma sa multilevel nasljeđivanjem.

class Animal{  
void eat(){System.out.println("eating");}  
}  
  
class Dog extends Animal{  
void eat(){System.out.println("eating fruits");}  
}  
  
class BabyDog extends Dog{  
  void eat(){System.out.println("drinking milk");}  
  
  public static void main(String args[]){  
    Animal a1,a2,a3;  
    a1=new Animal();  
    a2=new Dog();  
    a3=new BabyDog();  
  
    a1.eat();  
    a2.eat();  
    a3.eat();  
  }  
}

Ispis na ekranu:
eating
eating fruits
drinking milk

Primjer 1

class Animal{  
  void eat(){System.out.println("animal is eating...");}  
}  
  
class Dog extends Animal{  
  void eat(){System.out.println("dog is eating...");}  
}  
  
class BabyDog1 extends Dog{  
  public static void main(String args[]){  
    Animal a=new BabyDog1();  
    a.eat();  
  }
}

Ispis na ekranu: 
dog is eating...

Pošto BabyDog ne preklapa metodu eat(), to znači da je pozvana metoda eat() klase Dog.


Zadaci iz ovog poglavlja    Objektno orijentisano programiranje u Javi    Index