14 - referenciák, case objectek¶
Scalában minden összetett típus (az Int
, Double
, Boolean
, Long
stb. egyszerű típusok, ezekből a Java primitív típusai készülnek; de minden más típus) létrehozáskor a heap memóriában, dinamikusan jön létre. Vegyük például a Pont
típust még egyszer:
1 2 3 4 |
|
1 2 3 4 5 6 7 8 9 |
|
Pont(2,3)
hívást intézünk, akkor dinamikusan, a heap memóriában lefoglalódik egy új memóriaterület,
a két mezőnek megfelelő érték beáll a 2-re ill. 3-ra, majd ennek az újonnan létrehozott és tartalommal feltöltött memóriaterületnek
végső soron a címe kerül a p
értékbe.
Ezek után a q=p
értékadás hatására ez a cím másolódik át q
-ba, így a két érték egy-egy pointert tárol,
ami ugyanarra a memóriaterületre mutat.
(attól ne tartsunk, hogy nincs memória felszabadítás: a JVM mentalitása az, hogy nincs külön memória-felszabadító függvény, mint C-ben a free
,
hanem a JVM mellett fut egy garbage collector, aki ha észreveszi, hogy egy memóriaterületre már nem mutat senki, felszabadítja automatikusan.)
Teljesen hasonlóan, a Lista
case class
unk is leginkább valami efféle lehetne C-ben:
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 |
|
null
, mindig egy valid objektumra mutat, nincs referencia-aritmetika,
azaz nem tudjuk ,,eltolni'' mint egy pointert, hogy egy tömbben ,,arrébb'' indexeljünk, és szintaktikusan úgy kezeljük a referenciát,
mintha egy tényleges objektum lenne - pl. ponttal és nem nyíllal hivatkozzuk a mezőit).
Ez azt is jelenti, hogy pl. egy Lista
konstruálásakor valójában konstans idő alatt készül az új lista, mert nem másoljuk a farkát,
csak elrakjuk a címét egy mezőbe. (ahogy a kód legvégén, az egyelemu->nemuresLista->tail = ures;
hívásban is.)
Továbbá azt is jelenti, hogy az ==
operátor először is a két oldalán lévő referenciák címét hasonlítja össze, és ha azok egyenlőek,
akkor máris le tudja jelenteni, hogy true
; ha meg nem, akkor végignézi az adatmezők egyeztetését.
Mi a helyzet tehát akkor az üres listával:
1 2 3 4 |
|
UresLista
értéket, mindig egy új rész foglalódik le neki a memóriában,
ennek a címét megkapja az adott érték. Amikor meg ==
-t tesztelünk rá, és két külön helyen lévő példányát nézzük,
hogy egyenlőek-e (azok lesznek, hiszen adattag nincs), akkor eltart egy darabig, mire rájön a JVM,
hogy ezek nem ugyanazon a címen vannak, de ugyanolyan típusúak, és minden mezejük megegyezik.
case object¶
Mindezt megspórolhatjuk, ha case class
helyett case object
ként deklaráljuk az üres listát:
1 2 3 4 |
|
- Egy
case object
lényegében egy olyan típus, aminek egyetlenegy elemű az értéktartománya (tkp ez igaz volt azUresLista
ra mintcase class
ra is, csak több helyen is létrehozhattuk a memóriában ezt az egy értéket) - ez az egy érték a program futásának legelején létrejön egyetlen helyen a memóriában,
és innentől kezdve minden értékadásnál ezt az egy referenciát kapja minden ilyen típusú érték, az
UresLista
maga ez a referencia lesz - ez többek közt azért jó, mert csak egyszer foglal helyet a memóriában és gyorsabb rá az
==
ellenőrzés. - nincs neki argumentumlistája (ha lenne, nem hozhatnánk létre egyetlen objectként), a zárójelek kitevése fordítási hibát is okoz.
Ebből a lényeg: ha egy típus az 1
, akkor azt case object
ként hozzuk létre; ha extendelnie kell egy trait
et, azt is tudja
probléma nélkül.
Az Int Listánk most¶
A jelenlegi implementációnk:
1 2 3 |
|
1 2 3 4 5 |
|
Így ez a függvény azt adja vissza (tail rekurzív módon), hogy a paraméterként megadott listában előfordul-e a paraméterként megadott érték. Ha igen, akkor a második case illeszkedik akkor, amikor ahhoz a részlistához érünk, akinek a fejeleme pont a keresett elem (ekkor már mindegy, hogy mi a farok, ezért ott az underscore). Ha meg nem, akkor keresünk tovább a lista farkában (ekkor meg már nem számít, hogy mi is a fejelem; ha a harmadik case alternatívához érünk, akkor már tudjuk, hogy nem a keresett érték az).
Vagyis, egy case NemuresLista(‘value‘,_)
case egyenértékű egy case NemuresLista(v,_) if v==value
if guardos case-el.
Kérdések, feladatok¶
- Mik a főbb különbségek referencia és pointer közt?
- Hogy működik alapértelmezetten az
==
operátor? - Mi a különbség case class és case object között?