2011. március 9., szerda

Konstruktorok

Két kis feladat egy nagy multinacionális cég tesztjéből:

1) Mi a hiba az alábbi programban? Miért?

class X {
    X(int i) {
        System.out.println(i);
    }
}

class Y extends X {
    Y(int i) {
        System.out.println(i);
    }
}

2) Mi a hiba az alábbi kódban? Miért?

class Base {
    int i;
    Base(int j) {
        i = j;
    }
}

class Derived extends Base {
    Derived(int j) {
        System.out.println(j);
        super(j);
    }
}

A megoldás:

1)

A kód nem fordul, mert nincs az X osztályban alapértelmezett konstruktor. Feloldható az Y osztályban a
super(i);
utasítás használatával a
System.out.println(i);
helyett.

2)

Itt a helyzet hasonló, tetézve azzal, hogy a szülő konstruktorát a super kulcsszóval mindig a legelső helyen kell meghívni.


A miértre is egyszerű a válasz, aki elolvassa az alábbiakat, meg fogja érteni. (A sietősek kedvéért kiemeltem a lényeget.)


Ha egy osztály nem ad meg semmilyen konstruktort, akkor a fordító automatikusan biztosít egyet: ez a paraméterek nélküli alapértelmezett konstruktor (default constructor).

  • Ha az osztály az Object leszármazottja, egy üres (paraméterek nélküli) alapértelmezett konstruktort kap
  • Egyéb esetben pedig a szülő alapértelmezett (paraméterek nélküli) konstruktorát hívja meg a super kulcsszó használatával

Fordítási idejű hibát fogunk látni, ha utóbbi esetben az ősosztály alapértelmezett konstruktora nem elérhető vagy nincs.

Alapértelmezett konstruktor nem dobhat semmilyen kivételt (a nem alapértelmezettek dobhatnak, ezt a throws kulcsszó használatával kell jelezni). Az alapértelmezett konstruktor olyan elérhetőséggel rendelkezik, amilyennel az osztályt magát deklaráljuk.

Azaz, minden osztálynak van konstruktora, akkor is, ha explicit azt nem adtuk meg. Azonban, figyeljünk arra, hogy az alapértelmezett konstruktort csak akkor kapja meg automatikusan egy osztály, ha semmilyen konstruktora nincs. Ha már csak egyet is megadunk, akkor ez a szabály nem él. Ez okozhat problémákat, többek között a fenti esetekben is. Az ökölszabály tehát:

Ha bármilyen konstruktort definiálsz egy osztályban, akkor az alapértelmezettet mindenképpen meg kell adni.



Azaz a válasz a miértre az, hogy mivel az Y osztályunk nem hívja meg az ősosztályának egyetlen konstruktorát sem, a fordító azt feltételezi, hogy az ősosztály alapértelmezett konstruktorát hívjuk az első helyen, de az X osztályban, mivel explicit megadtunk már egy konstruktort, a fordító nem rakja be az alapértelmezettet, azaz nem tudja azt meghívni, így hibát jelez. Ez a helyzet a második esetben is, a már tárgyalt super kulcsszó rossz elhelyezése mellett.


Olvasnivaló:
Java language specification 3rd edition
Java world - Understanding constructors
Java Tutorial: Constructors

Nincsenek megjegyzések:

Megjegyzés küldése