Tech, szoftvertervezés és programozás

Szoftverfejlesztés, Shaderprogramozás, DirectX

  • A betűméret növelése
  • Alapértelmezett betűméret
  • A betűméret csökkentése
Címlap Programozás Metódusok túlterhelése és felülírása

Metódusok túlterhelése és felülírása

E-mail Nyomtatás PDF
Olvasóink értékelése: / 1
ElégtelenKitűnő 
OverloadA modern programozási nyelvek számos szolgáltatással kényeztetnek minket.
Mindazonáltal marad még épp elég kihívás az ember számára, attól nem kell tartanunk, hogy elkényelmesednek az agytekervényeink. ;-)
A következőkben egy érdekes témakörrel szeretnék foglalkozni: a metódusok túlterheléséről (overload) és felülírásáról (override) lesz szó. Példákon keresztül tárgyalom a témakört, és bemutatásra kerül egy potenciális csapda is.
A témakört a Java szemszögéből kerül bemutatásra.
A metódusfelülírás a többalakúságot valósítja meg a Java-ban és a C++-ban is. (A metódus felülírás megvalósítása eltér a C++-belitől, ugyanis a Java esetében nem kell, pontosabban nem lehet virtuális függvényekkel bajlódni: alapból minden nyilvános(public) és védett(protected) metódus felülírható a származtatott osztályokban.)
Lássunk egy konkrét példát. A következő osztályhierarchiával dolgozunk:
class A <- class B <- class C
és az implementáció:
    class A {
    String name() { return "A"; }
    }
    
    class B extends A {
    String name() { return "B"; }
    }
    
    class C extends B {
    String name() { return "C"; }
    }

Minden származtatott osztály felülírja a name() metódust. Teszteljük a többalakúságot működés közben:
    // létrehozunk egy listát, amely A típusú elemeket tárol
    List genericList = new ArrayList(3);
    genericList.add(new A()); // dinamikus (runtime) típus A
    genericList.add(new B()); // dinamikus (runtime) típus B
    genericList.add(new C()); // dinamikus (runtime) típus C

    System.out.println("A felülírt metódusok meghívása -> az objektum dinamikus típusa dönti el, melyik kerül meghívásra");
    for(A elem : genericList)
    {
        System.out.println(elem.name());
    }

A futás az elvárt eredményt produkálja:
A felülírt metódusok meghívása -> az objektum dinamikus típusa dönti el, melyik kerül meghívásra
A
B
C

Lássuk a túlterhelést.
Hozzuk létre egy metódusnak a túlterhelt változatait, amelyek mindössze a paraméter típusában térnek el egymástól:
    static private void printName(A a) {
        System.out.println("A");
    }
    
    static private void printName(B b) {
        System.out.println("B");
    }
    
    static private void printName(C c) {
        System.out.println("C");
    }


A printName() metódusnak egy ciklusban átadjuk a listánk elemeit, remélve, hogy az előzőhöz hasonló kimenetet produkál:
    for(A elem : genericList)
    {
        printName(elem);
    }

Az eredmény:
A
A
A

Nem erre számítottunk, és ez egy alattomos hibaforrás is lehet. A polimorfizmus a felülírt metódusokra vonatkozik: az objektum dinamikus, futásideji típusa dönti el, hogy melyik metódus kerül meghívásra.
A túlterhelés esetében egy metódus paraméterként kapja meg az objektumot - tahát nem az objektum tagfüggvényéről van szó, ezért nem is kapcsolódik annak dinamikus, futásideji típusához. Éppen ezért a paraméter statikus, fordítás-idejű típusa alapján dől el, melyik metódus hívódik meg.
Amennyiben valamiért mégis elkerülhetetlen ez a fajta megvalósítás, akkor megoldható némi körbeprogramozással.
Az általánosabb paraméterű metódus leellenőrzi a bemenő paraméter dinamikus típusát, majd ha az származtatott típus, akkor meghívásra kerül a specializált változat:
    /**
     * ez egy workaround, ne alkalmazzuk, hacsak nem feltétlenül szükséges
     */
    static private void printNameOK(A a) {
        if(a instanceof C) {
            printNameOK((C)a);
        }
        else if (a instanceof B) {
            printNameOK((B)a);
        }
        else
        System.out.println("A");
    }
    
    static private void printNameOK(B b) {
        System.out.println("B");
    }
    
    static private void printNameOK(C c) {
        System.out.println("C");
    }

Ezáltal az elvárt kimenetet kapjuk:
A
B
C

Jó programozást!

Üdvözlettel,
Nyisztor Károly