A ChucK nyelv objektum rendszerének alapjául a C++ és Java nyelvek konvenció szolgáltak.
- Definiálható egyedi osztály, mint új típus és az példányosítható.
- A nyelv támogatja a polimorf öröklődést (ugyanúgy mint Javában; C++-ban virtuális öröklődésnek hívják).
- Minden objektum változó referencia (mint Javában), de a példányosítás C++-szerű (lásd alább).
- Van alapértelmezett osztály könyvtár.
- Minden objektum az Object osztály leszármazottja (mint Javában).
Az egyértelműség végett az alábbi kifejezéseket vezetjük be:
- osztály: adatok (adattagok) és viselkedés (metódus) absztrakciója
- osztály: típust definiál
- objektum: egy osztály egy példányosítása
- referencia változó: indirekten hivatkozik egy objektumra - nem az objektum maga.
ChucK-ban minden objektum változó referncia változó (mint Javában).
- referencia értékadás: egy objektum referenciájáról készít másolatot, ez a referencia kerül a referencia változóba.
Az objektumról nem jön létre másolat. ChucK-ban minden objektum értékadás referencia értékadás.
Beépített osztályok
A ChucK nyelv rendelkezik néhány nyelv szinten rögzített előre definiált osztállyal.
Néhány példa ezek közül:
- Object: ősosztálya minden ChucK-beli objektumnak.
- Event: szinkronizáló mechanizmus; kiterjeszthető egyéni események lekezeléséhez.
- Shred: absztrakció a nem preemtív (kívülálló folyamat által nem megszakítható) párhuzamos ChucK folyamathoz.
- UGen: ősosztálya az UGen (jelgenerátor) osztálynak.
- UAnae: ősosztálya az UAnae (jel analizátor) osztálynak.
Objektumok
// Tegyük fel, hogy a Foo osztály már definiálva van
// Foo típusú objektum létrehozása, eltárolása a bar referencia változóba
Foo bar;
A fenti kód hatására:
- deklaráljuk a
bar
nevű refencia változót, melynek típusa Foo
.
- létrehozunk egy új
Foo
típusú példányt, melynek referenciáját a bar
változóba tároljuk.
Érdemes megfigyelni, hogy Javával ellentétben, itt egyszerre kerül deklarálásra a referencia változó
és jön létre az osztály példánya, melynek referenciája a változónak adódik értékül. Szintén érdemes
megjegyezni, hogy C++-al ellentétben bar
csak egy referencia és nem az objektum maga.
// deklarálható olyan referencia változó is ami nem mutat semmire
// ekkor a referencia null értéket tárol
Foo @ bar;
A fenti kód csak deklarál egy referencia változót és null
-ra inicializálja.
// új példány referenciájának értékadása
new Foo @=> Foo @ bar; // ekvivalens: Foo bar;
A fenti kód ugyanazt eredményezi, mint feljebb a Foo bar;
kifejezés.
A new
operátor egy osztály (jelen esetben Foo) egy példányát hozza létre. Az @=>
operátor hajtha végre a referencia értékadást.
// ugyanarra az objektumra több változóval is hivatkozhatunk
// új változó és példányosítás
Foo bar;
// új változó és referencia értékadás
bar @=> Foo @ duh;
// jelen esetben bar és duh változók ugyanarra az objektumra hivatkoznak
A nyelv referencia számlálókon keresztül vizsgálja az objektumok élettartamát,
a szemétgyűjtés automatikus.
(Ez a funkcionalitás a leírás készítésekor implementálás alatt állt.)
Osztályok tartalmazhatnak adatot és viselkedést, adattagok és metódusok formájában.
Ezek a '.' jellel érhetőek el: referencia.adattag
és referencia.metódus()
alakban.
// Tegyük fel, hogy a Foo osztály már definiált és rendelkezik
// compute metódussal, ami két egész típusú értéket vár és egésszel tér vissza
Foo bar; // változó deklaráció és objektum példányosítás
// compute() függvény meghívása, a visszatérési érték boo változóban tárolása
bar.compute(1, 2) => int boo;
Osztályok
Ha egy osztály már korábban definiálva lett a ChucK virtuális gépben
(vagy ugyanabban a forrásfájlban vagy különálló fájlban publikus osztályként.),
akkor a primitív típusokhoz hasonlóan példányosítható.
Egy osztály hatásköre a shred (forrásfájl), amiben definiálásra került, így
nem lesz névütközés, ha párhuzamos futtatás esetén több forrásban is azonos
néven lett definiálva osztály. Figyelem: ez a működés csak a nem publikus osztályokra vonatkozik!
Az osztályok viselkedések és adatok halmazát enkapszulálják. Új objektum típus definiálása
a class
kulcsszóval történik, melyet az osztály neve követ.
// X osztály definiálása
class X
{
// osztály törzsének kódja
}
Ha egy osztályt public
kulcsszóval definiálnak, akkor az a ChucK
virtuális gép központi névterébe kerül (nem pedig a lokális névtérbe), ezáltal
más programokból is példányosítható, melyek később kerülnek lefordításra. Forrásfájlonként
egy publikus osztály definiálható!
// publikus osztály definiálása
public class Popular
{
// publikus osztály törzsének kódja
}
// nem publikus osztály definiálása
class Unpopular
{
// nem publikus osztály törzsének kódja
}
// Popular és Unpopular egyaránt szabadon használható a jelenlegi forrásfájlban
// csak Popular használható másik fájlban, Unpopular nem!
Példány szintű adattagok/függvények
// X osztály definiálása
public X
{
// pre-konstruktor kód
100 => int a;
for ( 0 => int b; b < 5; ++b)
{
<<<"Pre-konstruktor szöveg kiírás.">>>;
}
// adattagok definiálása
int i;
float x;
Event e;
// metódusok definilása
fun int getI() {return i;}
fun void setI(int value) { value => i;}
fun float calculate( float x, float y)
{
// függvénytörzs
}
fun void print()
{
<<<i, x, e>>>;
}
}
// X példányosítása
// a pre-konstruktor kód ekkor fut le
X x;
//függvényhívások, adattagok elérése
x.setI(4);
.25 => x.x;
x.print();
Konstruktor
Jelenleg nem támogatott a hagyományos konstruktorok használata. Lehetőség van
viszont úgynevezett pre-konstruktort használni. A kód, ami az osztály defícióban
(és nem függvénybe ágyazva) szerepel az osztály példányosításakor mindig lefut, így
az felhasználható konstruktorként.
Osztály szintű adattagok/függvények
Az osztály szintű adattagok és metódusok az osztályhoz tartoznak, minden példány esetén ugyanarra
hivatkoznak. Osztály szintű adatok és műveletek példányosítás nélkül elérhetőek, végrehajthatóak az
osztály nevével hivatkozva: Osztálynév.statikusAdat
, Osztálynév.statikusFüggvény()
.
Jelenleg csak primitív típusú adattagot lehet osztályszintűnek deklarálni!
// X osztály definiálása
public X
{
// osztályszintű adattag
static int data;
// osztályszintű függvény
fun static int getData()
{
return data;
}
}
// nem szükséges példányt létrehozni az osztályszintű elemek használatához
2 => X.data;
<<<X.getData()>>>;
// példányosítjuk X-et
X x1;
X x2;
<<<x1.data, x2.data>>>;
5 => x1.data;
<<<x1.data, x2.data>>>;
Öröklődés
A ChucK nyelvben is van lehetőség az öröklés használatára az extends
kulcsszó használatával. A nyelv támogatja a polimorf öröklést, így az ősosztály referenciája
hivatkozhat valamelyik leszármazottjára is. Jelenleg a láthatóságot befolyásoló kulcsszavak
nincsenek implementálva, így minden alapértelmezetten publikus.
// X osztály definiálása
class X
{
fun void doThat()
{
<<<"Hi!">>>;
}
fun void yo()
{
<<<"Yo!">>>;
}
int data;
}
// származtatás X-ből
class Y extends X
{
// függvény felüldefiniálás
fun void doThat()
{
<<<"Go away!">>>;
}
// csak a leszármazottban definiált függvény
fun void child()
{
<<<"Just a kid!">>>;
}
}
// Y példányosítása
Y y;
// felüldefiniált függvény hívása
y.doThat();
// ősosztályban definiált függvény hívása
y.yo();
// az ős adattagjait is megörökli a leszármazott
<<<y.data>>>;
// X típusú referencia változó
X @ x;
// polimorf öröklődés
y @=> x;
x.doThat();
x.yo();
y.child();
// x kasztolása Y típusúra, így elérhető a leszármazott függvénye
(x $ Y).child();
Túlterhelés
Osztályok esetén a függvények túlterhelése megegyezik a sima függvények túlterhelésének
működésével.