Objektum-orientált programozás
Osztályok
Az Oz az objektum orientált programozást is támogatja, léteznek a megfelelő szintaktikai elemek, és az implementációja is megközelítőleg annyira hatékony, mint a függvényhívásoké.
Az osztályok olyan chunk-ok, amelyek tartalmaznak:
- Metódustáblát
- Attribútumokat, amiket az osztály minden példánya tartalmazni fog. Minden attribútum állapottal rendelkező cella, amit név szerint érünk el. Ez lehet atom vagy név.
- Feature-öket, amiket az osztály minden példánya tartalmazni fog. Az a különbség attribútum és feature között, hogy a feature immutable.
- Az osztályok állapot nélküli értékek. Ellentétben a Smalltalk-kal vagy a Java-val, csak azt írják le, hogy az objektumok hogyan viselkedjenek.
A következő példa egy számláló osztály.
declare Counter
local
Attrs = [val]
MethodTable = m(browse:MyBrowse init:Init inc:Inc)
proc {Init M S Self}
init(Value) = M in
(S.val) := Value
end
proc {Inc M S Self}
X inc(Value)=M
in
X = @(S.val) (S.val) := X+Value
end
proc {MyBrowse M=browse S Self}
{Browse @(S.val)}
end
in
Counter = {NewChunk c(methods:MethodTable attrs:Attrs)}
end
Más megközelítésből class-ként is létrehozhatjuk a következő képpen:
class Counter
attr val
meth browse
{Browse @val}
end
meth inc(Value)
val := @val + Value
end
meth init(Value)
val := Value
end
end
Az osztályok statikus metódusait vesszővel lehet kijelölni.
A metódusokból @A szimbólummal hivatkozhatunk az A nevű attribútumra, értéket pedig az A := E utasítással adhatunk neki. Az attribútumok tartalmazzák az osztály állapotát, értéket adhatunk neki, akkor is, ha már van értéke (destruktív értékadás, ez csak attribútumok esetén megengedett), és csak az objektumon belülről látszik.
A metódusok osztályokhoz rendelt eljárások.
Az osztályok metódusai egymást is hívhatják, ha van egy C nevű osztály m(…) metódus fejjel, a metódusokban szereplő C, m(…) ugyanazon az objektumon meghívja az m(…) metódust. Az OZ ezt hívja statikus metódushívásnak, ilyen csak metódus törzsében szerepelhet.
Névtelen osztályok az X = class $ ... end formában definiálhatók.
A New/3 generic eljárással hozhatunk létre egy objektumot az osztályból, ennek első paramétere az osztály, a második pedig az inicializáló metódus. Egy objektum metódusát { objNev metodNev(parameter_1 … ) } formában hívhatjuk meg.
Az objektumok „feature” –öket is tartalmazhatnak, ezek a rekordokhoz hasonló, állapotmentes komponensek, a következő formában deklaráljuk őket:
class X …
feat A1[:initVal_1] … AN[:initVal_n]
….
end
Mint a rekordoknál, itt a feature –öknek is van egy hivatkozott mezőjük, amit bármilyen OZ értékkel le lehet kötni. Egy objektum feature –ére az infix „.” operátorral hivatkozhatunk. Objektum létrehozásakor a feature –ök inicializálása initVal_i –re történik, ezt azonban nem kötelező megadni.
Objektumok
Objektumokat kérhetünk az osztálytól. Az Oz belső szerkezetében valójában az objektum Object típusú, de van egy mutatója az ő őseinek számító classokra.
Példa:
declare C
{NewObject Counter init(0) C}
Öröklődés
Létezik, a szülőket fel kell sorolni a deklarációnál a from kulcsszó segítségével:
class A from B ... end
Két feltétele van az öröklésnek.
Az egyik, hogy a származtatás aciklikus, tehát az öröklődési gráf mindenképpen háló lesz. A másik, hogy ne örököljön azonos nevű tagot az osztály több ősétől.
A következő példát az Oz nem engedi lefordítani a többszörös öröklődés ütközése miatt.
class A meth m(...) ... end end
class B meth m(...) ... end end
class C from A B end
Illegális származtatás esetén a fordító nem jelez hibát és a program megfelelően működik, mindaddig, míg nem próbáljuk meg a problémát okozó metódust elérni. Ekkor futási idejű hibát kapunk.
A láthatóság szabályozására nincs külön nyelvi elem, de elérhető, hogy egy metódus csak az osztályon belül látszódjon. A nyelv megkülönbözteti a public, protected és private metódusokat, de nem ad erre direkt jelölést.
A „normális” ún. literállal címkézett metódus publikus (public):
class C from …
meth a(…) … end
…
end
Metódusokat azonban nem csak literálokkal, hanem változónévvel is címkézhetjünk, az ilyen metódusok lesznek privátok (private) az osztályra nézve:
class C from …
meth A(…) … end
…
end
Védett (protected) metódust pedig úgy definiálhatunk, hogy először megadunk egy private metódust, majd azt eltároljuk egy attribútumban:
class C from …
attr pa:A
meth A(X) … end
meth a(…) {self A(5)} … end
…
end
Ezután a C osztály leszármazottaiban az állabi módon elérhető lesz az A védett metódus:
class C1 from C
meth b(…) L=@pa in {self L(5)}… end
…
end
Polimorfizmus, dinamikus kötés
Az objektumok metódusait a rendszer mindig dinamikusan köti.
Interfészek
Nincsenek interfészek.