A polimorfizmusról általában
  A dinamikus polimorfizmus

Az explicit dinamikus polimorfizmus



Lássuk először is, mit jelent az 'explicit' jelző:

A lehetséges kiszolgáló objektumok típusára explicit megkötés létezik, ezeknek az objektumoknak valamilyen 'rokonságban' kell lenniük egymással.

Tehát nemcsak arra van megkötés, hogy a ténylegesen felhasználni kívánt metódusokkal rendelkezzenek az objektumok. A rokonsági kapcsolat lehetséges változatai:

Explicit dinamikus polimorfizmus megvalósítása
örököltetés segítségével

Vegyünk egy nagyon egyszerű, Java nyelvű szemléltető példát, melyben örököltetést fogunk használni.

Képzeljünk el egy interaktív számítógépes játékot, melyben a harcos szereplők szükség esetén védekezni tudnak. Van egy függvény, amely a paraméterként kapott harcossal különféle műveleteket végeztet, a példa egyszerűsége kedvéért most csak védekezést:

  static void HarcostMűködtet(Harcos H){
    H.Védekezik();
  }

A Harcos általánosan használt alap-típusának megvan a jól bevált módszere a védekezésre:

  class Harcos{
    //...
    public void Védekezik(){
      System.out.println("Lövöldözöm midhalálig!");
    }
  }

Létezik a játékban a harcosnak egy kevésbé teljesítményorientált változata is, aki más algoritmust használ, amikor megtámadják :

  class GyávaHarcos extends Harcos{
    //...
    public void Védekezik(){
      System.out.println("Fejvesztve menekülök!");
    }
  }

Láthatjuk, hogy a GyávaHarcos egyfajta Harcos, hiszen abból az osztályból van örököltetve. Ezért a Java nyelv szabályai szerint a HarcostMűködtet függvénynek mindkét típusú objektumot átadhatjuk paraméterként, tehát ez a programrészlet szintaktikailag helyes:

  Harcos h1 = new Harcos();
  Harcos h2 = new GyávaHarcos();

  HarcostMűködtet(h1);
  HarcostMűködtet(h2);

és a kimenet természetesen ez lesz:

  Lövöldözöm midhalálig!
  Fejvesztve menekülök!

A HarcostMűködtet függvénynek nem adhatunk át paraméterként bármely tetszőleges objektumot, melynek van Védekezik() metódusa, hanem csak Harcos, vagy abból örököltetett típusút. Ezért nevezzük ezt az esetet explicit polimorfizmusnak.

Dinamikusnak pedig azért nevezzük, mert a program fordításakor nem mindig lehet eldönteni, hogy adott ponton éppen mi lesz egy adott objektum konkrét típusa. Tegyük fel például, hogy a program futása közben valahol ezt kérdezi a felhasználótól:

  Harcost (1) vagy GyávaHarcost (2) hozzak létre?

és a felhasználó válaszától függően készít el egy objektumot, majd később felhívja a HarcostMűködtet függvényt:

  Harcos h;

  if(válasz == 1)
    h = new Harcos();
  else
    h = new GyávaHarcos();

  ...

  HarcostMűködtet(h);

Világos, hogy a program fordításakor még elvileg sem lehet tudni, milyen típusú objektumot kap majd paraméterként a HarcostMűködtet függvény - hiszen ugyanazon hívási helyen kaphat hol ilyet, hol olyat. Ennek ellenére mindig a kívánt, az objektum tényleges típusának megfelelő metódus fog felhívódni!

Explicit dinamikus polimorfizmus megvalósítása
Java interfész segítségével

A Java nyelvben a másik lehetséges - lazább! - megkötés a 'rokonságra' az, hogy valamely interfész implementálása van előírva. Dolgozzuk át a
fenti mintapéldát úgy, hogy interfész szerepeljen benne:

  interface I_Harcos{
    public void Védekezik();
    public void Támad();
    //... és még sok más metódus
  }

Ezt az interfészt implementálja a bátor harcos:

  class Harcos implements I_Harcos{
    public void Védekezik(){
      System.out.println("Lövöldözöm midhalálig!");
    }
  
    public void Támad(){
      System.out.println("Vadul nyomulok előre és ordítok!");
    }
    //...
  }

és a gyáva is:

  class GyávaHarcos implements I_Harcos{
    public void Védekezik(){
      System.out.println("Fejvesztve menekülök!");
    }
  
    public void Támad(){
      System.out.println("Óvatosan settenkedem előrefele!");
    }
    //...
}

A HarcostMűködtet függvény paramétere most persze I_Harcos típusú:

  static void HarcostMűködtet(I_Harcos H){
    H.Védekezik();
  }

A függvény hívása így néz ki:

  I_Harcos h1 = new Harcos();
  I_Harcos h2 = new GyávaHarcos();

  HarcostMűködtet(h1);
  HarcostMűködtet(h2);

A kiszolgáló objektum típusa most sem lehet tetszőleges, csakis olyan osztály felel meg, amely implementálja az I_Harcos interfészt.



Az explicit polimorfizmus természetéből adódóan mindig ellenőrzött fajtájú, tehát ha nem megfelelő típusú objektumot akarunk adott helyen felhasználni (a HarcostMűködtet függvénynek paraméterként átadni), akkor erre már a fordítóprogram figyelmeztet minket hibajelzés formájában.


A dinamikus polimorfizmus
  A polimorfizmusról általában