A gyakorlat anyaga¶
Ezen a gyakorlaton megismerkedünk a JavaScript nyelven történő objektumorientált programozással.
Osztályok, objektumok¶
A korábban megismert objektumorientált paradigma alapvető elemei az osztályok. Ezek tulajdonképpen azonos tulajdonságokkal és viselkedéssel rendelkező objektumok általánosításai, formai leírásai.
Érdekes módon a JavaScriptben nem mindig voltak osztályok. Az osztály, mint beépített nyelvi elem csupán a 2015-ös ECMAScript6 (ES6) szabványban jelent meg. Arról, hogy az osztályok bevezetése előtt milyen megoldások voltak JavaScriptben az objektumok általános formai leírásának elkészítésre, az előadáson lesz szó.
Osztályok létrehozása¶
A fentebb említett ECMAScript6 szabvány bevezette a class
kulcsszót, aminek segítségével osztályokat hozhatunk létre JavaScriptben.
Példa: Egy Jarmu
nevű osztály létrehozása
1 2 3 |
|
Adattagok, metódusok¶
Egy osztálynak lehetnek adattagjai, illetve metódusai (tagfüggvényei). Ezekre JavaScriptben a .
(pont) operátorral tudunk hivatkozni.
Az osztály metódusait a függvényekhez hasonló módon hozhatjuk létre, azzal a fontos különbséggel, hogy a függvények definiálásakor használt function
kulcsszót elhagyjuk.
Példa: Egy paraméter nélküli info()
és egy egyparaméteres utastFelvesz()
metódus
1 2 3 4 5 6 7 8 9 |
|
Hasonlóképpen, mint ahogy azt Pythonban tanultuk, JavaScriptben sem deklaráljuk az adattagokat külön az osztályban. Az adattagok létrehozása és inicializálása itt is a konstruktorban történik.
Konstruktor¶
JavaScriptben a constructor()
névre hallgató speciális metódus lesz az osztály konstruktora. Ez természetesen akkor kerül meghívásra, amikor az osztályt példányosítjuk. A konstruktort használjuk az osztály adattagjainak létrehozására és inicializálására.
Amennyiben az osztályunkba nem írunk konstruktort, akkor az interpreter automatikusan gyártani fog egy paraméter nélküli konstruktort (default konstruktort), ami az osztály példányosításakor fog meghívódni.
JavaScriptben a this
kulcsszóval hivatkozhatunk az aktuális objektumra. Ha egy osztályon belül hivatkozni szeretnénk egy adattagra vagy egy metódusra, akkor a kérdéses adattag vagy metódus neve elé mindig kötelezően ki kell írni a this
kulcsszót!
Példa: Egy két paraméteres konstruktor, amely paraméterei alapján inicializáljuk a marka
és sebesseg
adattagokat
1 2 3 4 5 6 |
|
JavaScriptben továbbra sincs function overload. Ha azt szeretnénk elérni, hogy egy metódust többféle, eltérő paraméterezéssel is tudjunk használni, akkor használjuk a default függvényparamétereket!
Példa: Írjuk át a Jármű osztály konstruktorát úgy, hogy a sebesség paraméter értékét ne legyen kötelező megadni, alapértéke legyen 0!
1 2 3 4 5 6 |
|
Példa: Egészítsük ki az osztályunkat a következőkkel:
- A konstruktorban hozzunk létre egy
utasok
adattagot, amit egy üres tömbbel inicializáljunk! - Írjuk meg az
utastFelvesz()
metódust, amely egy utas nevét (szöveges adat) várja paraméterül! A metódus szúrja be a paraméterül kapott utas nevét azutasok
tömb végére! - Készítsük el az
info()
metódust, ami kiírja a jármű márkáját, sebességét és az utasok számát!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Objektumok létrehozása¶
A példányosítás során az osztályból egy objektumpéldányt hozunk létre.
Az osztály példányosítása, avagy egy új objektum létrehozása JavaScriptben a new
kulcsszó segítségével történik. A példányosításkor meghívjuk az osztály konstruktorát, és átadjuk neki a megfelelő paramétereket (ha vannak).
Példa: A Jármű osztály példányosítása, metódusok meghívása
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Kimenet
Škoda márkájú jármű, melynek sebessége 90 km/h, és 1 utast szállít. Ikarus márkájú jármű, melynek sebessége 0 km/h, és 0 utast szállít.
Láthatóságok, getterek, setterek¶
A Pythonhoz hasonló módon JavaScriptben sem tudjuk szabályozni módosítószavakkal az adattagok láthatóságát (vesd össze: Java). Alapértelmezett módon minden adattag publikus, azaz mindenhonnan elérhető.
Konvenció alapján az adattag neve előtti egyszeres alulvonás jelzi azt, hogy az adattag nem publikus használatra van szánva ("private adattag"). Viszont ettől az adattag kívülről továbbra is elérhető lesz!
Példa: Jelezzük, hogy a márka és sebesség adattagokat nem publikus használatra szánjuk!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Ha a nem publikus használatra szánt adattagok szabályozott elérését és módosítását szeretnénk elérni JavaScriptben, akkor készíthetünk ezekhez az adattagokhoz gettereket, illetve settereket.
JavaScriptben a gettert, valamint a settert property-ként valósíthatjuk meg. A get property-t a get
, míg a set property-t a set
kulcsszóval hozhatjuk létre. A property-k használatával szabályozott módon kérhetjük le és állíthatjuk be adattagok értékét úgy, hogy kívülről azt a látszatot keltjük, mintha új, publikus adattagokkal dolgoznánk.
Példa: Készítsünk gettert és settert az _sebesseg
adattaghoz!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Kimenet
A sebesség értéke csak nemnegatív szám lehet! 60
Figyelem
Fontos, hogy a property és az adattag neve mindig eltérő legyen, különben végtelen rekurzióba futunk! A példában a property neve sebesseg
(alulvonás nélkül), az adattag neve ettől eltérő módon _sebesseg
(alulvonással).
Feladat: A fenti mintájára készítsünk get és set property-t a _marka
adattaghoz is!
Öröklődés¶
A korábbi tanulmányainkból ismerős lehet számunkra az öröklődés fogalma. Ez egy osztályok közötti kapcsolat, amely egy úgynevezett ősosztály (szülőosztály) és egy gyermekosztály (leszármazott osztály) között valósul meg. A gyermekosztály tulajdonképpen az ősosztályának egy speciális változata lesz (pl. a Kutya
osztály az Allat
osztály gyermeke, hiszen minden kutya egyben állat is).
Az öröklődés során a gyermekosztály megörökli az ősosztályának összes adattagját és metódusát. A gyermekosztályban létrehozhatunk az örökölt adattagokon kívül még egyéb adattagokat, metódusokat, illetve lehetőségünk van az örökölt metódusok működésének felüldefiniálására is (overriding).
JavaScriptben az öröklődést a következő szintaxissal adhatjuk meg:
1 2 3 |
|
Fontos megjegyezni, hogy JavaScriptben csak egyszeres öröklődés van, tehát egy osztálynak nem lehet kettő vagy több ősosztálya.
A gyermekosztályból hivatkozhatunk az ősosztályra, annak adattagjaira és metódusaira a super
kulcsszóval. Ennek segítségével meghívhatjuk az ősosztály konstruktorát az adott osztályon belül. Ha a gyermekosztályban nem hozunk létre új adattagot, akkor az ősosztály konstruktorának meghívása elhagyható.
Példa: Hozzunk létre egy Auto
osztályt, ami az imént elkészített Jarmu
osztályból származik!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
|
Kimenet
TÜTŰŰŰ! Trabant autó, (sebesség: 40 km/h), utasok száma: 0, önvezető: nem Tesla autó, (sebesség: 130 km/h), utasok száma: 2, önvezető: igen
Típusellenőrzés¶
Amint azt korábban láthattuk, a typeof
operátorral le tudjuk kérni, hogy egy adott objektum adott típusú-e.
1 2 |
|
Fontos megjegyezni, hogy a typeof
csak beépített típusokra működik! Ha egy saját osztályból példányosított objektumról szeretnénk eldönteni, hogy adott típusú-e, akkor az instanceof
operátor használatos. Az obj instanceof ClassName
visszaadja, hogy az obj
objektum ClassName
osztály példánya-e.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Megjegyzés
Tömbök esetén is az instanceof
kulcsszót használhatjuk (tomb1 instanceof Array
), vagy az Array.isArray()
beépített függvényt.