Gyakorlati alapok III.
Rombolás helyett építkezés: a new parancs és a konstruktor függvény
Az előző fejezetek során...
...csak romboltuk az osztályokat és metódusaikat, igaz, a kódon belül ennek is megvan a maga jól meghatározott ideje és oka:
-
idő - például egyszer és mindenkorra lefutott a program,
-
ok - például garantáltan nem használjuk többé a kódrészletet (osztályt, metódust).
Amint azt már láthattuk és megszokhattuk az összetett adattípusoknál, a kódobjektumot a new operátor parancs kiadásával tudjuk felépíteni.
Egy osztály felépítése, létrehozása (úgymond példányosítása) során ugyanígy kell tennünk.
A new parancs mögött tehát egy nagyon összetett rendszerprogramozási folyamat húzódik meg:
-
memóriahely foglalása történik, még pedig a szükséges (dedikált) mennyiségben,
-
a new parancs meghívja az objektumhoz tartozó (az objektum osztályához tartozó) konstruktor függvényt,
-
referenciaként beállítja az objektum általunk megadott nevét. Például egy téglalapot menedzselő osztály esetében a példányosítás így nézhet ki: Teglalap teglalap = new Teglalap (5, 10); Az osztály saját típusa ekkor Teglalap, referenciája pedig teglalap lesz. Az Osztályneveket mindig nagybetűvel írjuk! (Az adatok, metódusok elnevezésének problémái című fejezet)
Ebben a bonyolult kódépítési folyamatban a konstruktor függvény elsődleges feladata az osztályból létrehozott objektum kezdeti értékeinek beállítása, inicializálása, tágabb értelemben az osztály felépítése.
A konstruktor neve kötelezően megegyező az osztály nevével, azonban mivel egy osztálynak több konstruktora is lehetséges, a paraméterlisták (azaz a konstruktorok szignatúrái) különbözhetnek (szignatúra - Ahol az elnevezésnek köze nincs a tartalomhoz: a metódus-túlterhelés című fejezet).
Az alábbi futtatható Java-kódban egy Teglalap osztályban 2 db, szignatúrájukban különböző konstruktor függvényt implementáltunk, valamint a szemléltetés kedvéért 1 kerület-, és 1 területszámító metódust. Kiszámításukhoz 2 db bemeneti adatra van szükségünk, a téglalap szélességére és magasságára, ezeket inicializáltuk is:
public int szelesseg = 3;
public int magassag = 2;
Láthatjuk, hogy mindkét konstruktorral végrehajtott példányosítás gond nélkül lefut...
Teglalap teglalap = new Teglalap ();
Teglalap teglalap2 = new Teglalap (5, 10);
...(jegyezzük meg, hogy ekkor 1 osztályból 2 különböző objektum keletkezik: teglalap és teglalap2!)...
...ám a 2. esetben a konstruktorban felülírtuk a bemeneti adatokat (Teglalap (5, 10)), ezért más végeredményt fogunk kapni:
public class Teglalap {
public int szelesseg = 3;
public int magassag = 2;
public Teglalap() {
}
public Teglalap(int szelesseg, int magassag) {
this.szelesseg = szelesseg;
this.magassag = magassag;
}
public int getKerulet() {
return (szelesseg + magassag) * 2;
}
public int getTerulet() {
return szelesseg * magassag;
}
public static void main(String[] args) {
Teglalap teglalap = new Teglalap ();
Teglalap teglalap2 = new Teglalap (5, 10);
System.out.println(teglalap.getKerulet());
System.out.println(teglalap.getTerulet());
System.out.println(teglalap2.getKerulet());
System.out.println(teglalap2.getTerulet());
}
}
Végeredmény:
10
6
30
50
Minden Java osztálynak tartalmaznia kell legalább 1 db konstruktor függvényt, ennek elkészítése az osztály alkotójának feladata. Ám ha ezt nem teszi meg, egy paraméter nélküli, lényegében üres konstruktort fog a rendszer generálni és meghívni. Az alábbi kódban töröltünk minden konstruktor függvényt, az objektum mégis hiba nélkül létrejön:
public class Teglalap {
public int szelesseg = 3;
public int magassag = 2;
public int getKerulet() {
return (szelesseg + magassag) * 2;
}
public int getTerulet() {
return szelesseg * magassag;
}
public static void main(String[] args) {
Teglalap teglalap = new Teglalap ();
System.out.println(teglalap.getKerulet());
System.out.println(teglalap.getTerulet());
}
}
Végeredmény:
10
6
További érdekesség, hogy a konstruktor függvény(ek) priváttá tételével (private) megtilthatjuk az osztály példányosítását. Ennek ellenőrzéséhez egy kicsit tovább kell macerálnunk a kódot:
1. hozzunk létre azonos csomagon (package) belül 1 további, Main nevű osztályt és a main() főmetódust tegyük át oda:
public class Main {
public static void main(String[] args) {
Teglalap teglalap = new Teglalap ();
Teglalap teglalap2 = new Teglalap (5, 10);
System.out.println(teglalap.getKerulet());
System.out.println(teglalap.getTerulet());
System.out.println(teglalap2.getKerulet());
System.out.println(teglalap2.getTerulet());
}
}
2. Ezzel párhuzamosan a Teglalap osztályból töröljük a main() főmetódust:
public class Teglalap {
public int szelesseg = 3;
public int magassag = 2;
public Teglalap() {
}
public Teglalap(int szelesseg, int magassag) {
this.szelesseg = szelesseg;
this.magassag = magassag;
}
public int getKerulet() {
return (szelesseg + magassag) * 2;
}
public int getTerulet() {
return szelesseg * magassag;
}
}
A Run - futtatás gombra kattintva a kód hiba nélkül le fog futni:
Végeredmény:
10
6
30
50
A konstruktorok priváttá tétele után azonban a kód már nem lesz futtatható, amint a hibaüzenet is fogalmaz: a konstruktor(ok) nem látható(k).
public class Teglalap {
public int szelesseg = 3;
public int magassag = 2;
private Teglalap() {
}
private Teglalap(int szelesseg, int magassag) {
this.szelesseg = szelesseg;
this.magassag = magassag;
}
public int getKerulet() {
return (szelesseg + magassag) * 2;
}
public int getTerulet() {
return szelesseg * magassag;
}
}
Végeredmény:
Exception in thread "main" java.lang.Error: Unresolved
compilation problems:
The constructor Teglalap() is not visible
The constructor Teglalap(int, int) is not visible
at Main.main(Main.java:4)