Java - Polimorfizam


Polimorfizam je važan koncept objektno orijentisanog programiranja (OOP). To jednostavno znači više oblika. To jest, isti entitet (metoda ili operator ili objekt) može izvoditi različite operacije u različitim scenarijima.


Primjer: Java polimorfizam

class Polygon {

  // metoda za prikazivanje oblika
  public void render() {
    System.out.println("Prikaz poligona...");
  }
}

class Square extends Polygon {

  // prikazuje kvadrat
  public void render() {
    System.out.println("Prikazivanje kvadrata...");
  }
}

class Circle extends Polygon {

  // prikazuje krug
  public void render() {
    System.out.println("Prikazivanje kruga...");
  }
}

class Main {
  public static void main(String[] args) {
    
    // kreiranje objekta Square
    Square s1 = new Square();
    s1.render();

    // kreiranje objekta Circle
    Circle c1 = new Circle();
    c1.render();
  }
}

U gornjem primjeru stvorili smo superklasu: Polygon i dvije potklase: Square i Circle. Primijetite upotrebu metode render(). Glavna svrha metode render() je generisanje oblika. Međutim, postupak prikazivanja kvadrata razlikuje se od postupka prikazivanja kruga. Zbog toga se metoda render() ponaša različito u različitim klasama. Ili, možemo reći da je render() polimorfan.



Zašto polimorfizam?

Polimorfizam nam omogućava stvaranje dosljednog koda. U prethodnom primjeru takođe možemo stvoriti različite metode: renderSquare() i renderCircle() za generisanje kvadrata, odnosno kruga. Ovo će raditi savršeno. Međutim, za svaki oblik moramo stvoriti različite metode, a to će učiniti naš kod nedosljednim.

Da bismo to riješili, polimorfizam u Javi omogućava nam stvaranje jedne metode render() koja će se ponašati drugačije za različite oblike.



Nadjačavanje Java metode

Tokom nasljeđivanja u Javi, ako je ista metoda prisutna i u superklasi i u podklasi, a metoda u podklasi poništava istu metodu u superklasi. To se naziva nadjačavanje metode. U ovom će slučaju ista metoda izvesti jednu operaciju u superklasi, a drugu operaciju u podklasi. Na primjer:


Primjer 1: Polimorfizam korištenjem metode nadjačavanja

class Language {
  public void displayInfo() {
    System.out.println("Zajednički engleski jezik");
  }
}

class Java extends Language {
  @Override
  public void displayInfo() {
    System.out.println("Java programski jezik");
  }
}

class Main {
  public static void main(String[] args) {

    // kreiranje objekta za Java klasu
    Java j1 = new Java();
    j1.displayInfo();

    // kreiranje objekta za Language klasu
    Language l1 = new Language();
    l1.displayInfo();
  }
}

U gornjem primjeru stvorili smo superklasu pod nazivom Language i podklasu pod nazivom Java. Ovdje je metoda displayInfo() prisutna i u Language i u Java. Upotreba displayInfo() služi za ispis informacija. Međutim, ispisuje različite informacije na Language i na Java. Na osnovu objekta koji se koristi za pozivanje metode, ispisuju se odgovarajuće informacije.





Preopterećenje Java metode

U Java klasi možemo stvoriti metode s istim imenom ako se razlikuju u parametrima. Na primjer:

void func() { ... }
void func(int a) { ... }
float func(double a) { ... }
float func(int a, float b) { ... }

Ovo je poznato kao preopterećenje metoda u Javi. Ovdje će ista metoda izvoditi različite operacije na temelju parametra.


Primjer 3: Polimorfizam korištenjem metode preopterećenja

class Pattern {

  // metoda bez parametarar
  public void display() {
    for (int i = 0; i < 10; i++) {
      System.out.print("*");
    }
  }

  // metoda s jednim parametrom
  public void display(char symbol) {
    for (int i = 0; i < 10; i++) {
      System.out.print(symbol);
    }
  }
}

class Main {
  public static void main(String[] args) {
    Pattern d1 = new Pattern();

    // pozivanje metode bez argumenata
    d1.display();
    System.out.println("\n");

    // pozivanje metoda s jedim parametrom
    d1.display('#');
  }
}

U gornjem primjeru stvorili smo klasu pod nazivom Pattern. Klasa sadrži metodu koja se zove display() koja je preopterećena.

// metoda bez argumenata
display() {...}

// metoda s jednim argumentom tipa char
display(char symbol) {...}

Ovdje glavna funkcija display() ispisuje uzorak. Međutim, na osnovu prosljeđenih argumenata, metoda izvodi različite operacije:

  • ispisuje obrazac *, ako nijedan argument nije prosljeđen, ili
  • ispisuje obrazac parametra, ako je prosljeđen jedan argument tipa char.


Polimorfne varijable

Varijabla se naziva polimorfna ako se odnosi na različite vrijednosti pod različitim uslovima. Objektne varijable (varijable instance) predstavljaju ponašanje polimorfnih varijabli u Javi. To je zato što se objektne varijable klase mogu odnositi na objekte svoje klase kao i na objekte njenih podklasa.


Primjer: Polimorfne varijable

class ProgrammingLanguage {
  public void display() {
    System.out.println("Učimo Java programski jezik.");
  }
}

class Java extends ProgrammingLanguage {
  @Override
  public void display() {
    System.out.println("Ovo je Java.");
  }
}

class Main {
  public static void main(String[] args) {

    // deklarisanje objektne varijable
    ProgrammingLanguage pl;

    // kreiranje objekta Animal klase
    pl = new ProgrammingLanguage();
    pl.display();

    // kreiranje objekta Java klase
    pl = new Java();
    pl.display();
  }
}

U gornjem primjeru stvorili smo objektnu varijablu pl klase ProgrammingLanguage. Ovdje je pl polimorfna varijabla. To je zato što:

  • U izjavi pl = new ProgrammingLanguage(), pl se odnosi na objekt klase ProgrammingLanguage. i
  • U izjavi pl = new Java(), pl se odnosi na objekt klase Java.