A Factor programozási nyelv

Objektum-orientált programozás

Osztályok, felhasználói osztályok(TUPLE)

A Factor, mint azt már említettük egy dinamikusan tipizált, objektumelvű nyelv. A literáloknak, típuskonstrukciók által kapott objektumoknak mind közös őse az object osztály (még a számtípusok is benne foglaltatnak a hierarchiába) és minden objektum futási időben magával hordozza a kanonikus osztályát, ami az esetleges dinamikus ellenőrzések miatt szükséges. Factorban sok más nyelvvel ellentétben a metódusokat nem az osztályba helyezzük el, hanem külön, az osztályokon operáló szavak megvalósításával. A Factor objektumrendszere egyébként tekinthető a Common Lisp Object System (CLOS) egy egyszerűbb változatának is.

Factorban lehetőség van természetesen felhasználói osztályokat is definiálni, de nem az osztályszerkezet tetszőleges pontjára illesztve be ezeket, hanem a teljes osztályhiearchia egy részeként létező TUPLE-osztályok egyes specializációjaként. Ez utóbbi látszólag megkötésnek tűnhet, de ez a fajta megoldás szinte átlátszatlan és nem okoz semmiféle komoly problémát. A TUPLE tehát egy felhasználói osztály, mely nevesített értékeket tartalmaz. Ezeket slotnak nevezzük és értékük kiolvasható, illetve beírható, méghozzá úgy, hogy nem kötjük meg milyen típusú objektumot írhatunk a slotokba - bár opcionális kritériumokat megfogalmazhatunk erre vonatkozóan, de ez nem kötelező.
Példák TUPLE-re:

TUPLE: circle radius ; ! circle nevű egy nevesített slot-al:radius TUPLE: rectangle width height ; ! rectangle nevű, két nevesített slot-al ! Slot-típusok: tetszőleges objektumok TUPLE: color { red integer } { green integer } { blue integer } ; ! accessorok kivételt dobnak rossz típusnál TUPLE: person { name read-only } { age integer initial: 0 } { department string initial: "Marketing" } manager ; ! Kezdeti értékek és read-only slotok is ! lehetségesek, illetve lehet keverni a ! hosszú { ... } és rövid pl. manager ! slotdeklarációkat TUPLE: student < person lecturer ; ! személyből öröklődő diák, 1 új slot-al

Ha megadunk típust, akkor futási idejű ellenőrzés van az adott slot accessoraiba beépítve és hasonló történik read-only esetben is, amikor is csak az ún. boa-konstruktorok adhatnak az adott slotnak értéket, egyébként csak olvasni lehet. Az initial: szó jelentése nyílvánvaló.

TUPLE-k használata

Konstruktorok, példányosítás

TUPLE osztályainkból objektumokat a new és a boa konstruktorokkal példányosíthatunk, de definiálhatunk saját konstruktorszavakat is, melyeknek konvenció szerinti neve <típusnév> legyen. A new egy tuple osztályból példányosít úgy, hogy minden slot felveszi az initial: által meghatározott értéket (ha nem adtuk meg, akkor ez f), a boa pedig "By Order of Arguments" tölti fel a slotokat kezdőértékkel. Saját konstruktorszót a szokott módon, ezek segítségével tudunk deklarálni.
Példák:

rectangle new ! minden f 100 200 rectangle boa ! minden a megfelelő color new ! itt is minden f person new ! initial: értékei feltöltődnek student new ! a konstruktor kódöröklése is látszik : <rectangle> ( w h -- r ) rectangle boa ; : <cirle> ( r -- c ) circle boa ; 50 <circle> ! saját konstruktor clear ! veremtakarításra jó, eddig még nem szerepelt

Slot accessorok

Ha van egy name nevű slot-unk, akkor name<<(getter), >>name(setter) és change-name szavakat használhatunk, amennyiben egy objektumunk, az adott típusból, a vermen van.
Példák:

: ( -- employee ) employee new 40000 >>salary ; ! Alapértelmezett érték adása saját konstruktorban : ( -- manager ) "project manager" >>position ; ! Egy másik konstruktor TUPLE: check to amount number ; SYMBOL: checks : ( to amount -- check ) checks counter check boa ; : biweekly-paycheck ( employee -- check ) [ name>> ] [ salary>> 26 / ] bi ; ! Getter-használat : positions ( -- seq ) { "junior programmer" "senior programmer" "project manager" "department manager" "executive" "CTO" "CEO" "enterprise Java world dictator" } ; : next-position ( role -- newrole ) positions [ index 1 + ] keep nth ; : promote ( employee -- employee ) [ 1.2 * ] change-salary [ next-position ] change-position ; ! Példa changer-használatra TUPLE: encapsulator { changer quotation } { changee integer } ; encapsulator new 5 >>changee [ 1 + ] >>changer ! Példa olyanra, hogy egy slot kódot tartalmaz

Öröklődés, metódusok, generikus függvények

Az öröklődés szintaktikai módját fent már láttuk, azonban nem beszéltünk eddig a kódöröklésről. Ez a nyelvi featúra a Factor nyelvben úgy jelenik meg, hogy definiálhatunk generikus szavakat, melyeket metódusokként valósíthatunk meg, írhatunk felül az egyes alosztályokban. A generikus szavak GENERIC: deklaráció után jönnek, a metódusok pedig M: után. Amikor egy generikus szót kell végrehajtani, akkor a rendszer megvizsgálja, hogy mi van a veremtetőn, mi a veremtető típusa és a neki megfelelő metódust hívja meg. Ilyenkor a rendszer a vermen lévő objektum kanonikus típusát vizsgálja, így megvalósítva a dinamikus kötést.
Egy példa az itt leírtakra:

USING: accessors kernel math math.constants math.functions ; GENERIC: area ( shape -- n ) GENERIC: perimiter ( shape -- n ) TUPLE: shape ; TUPLE: circle < shape radius ; M: circle area radius>> sq pi * ; M: circle perimiter radius>> 2 * pi * ; TUPLE: quad < shape width height ; M: quad area [ width>> ] [ height>> ] bi * ; TUPLE: rectangle < quad ; M: rectangle perimiter [ width>> 2 * ] [ height>> 2 * ] bi + ; : hypot ( a b -- c ) [ sq ] bi@ + sqrt ; TUPLE: parallelogram < quad skew ; M: parallelogram perimiter [ width>> 2 * ] [ [ height>> ] [ skew>> ] bi hypot 2 * ] bi + ; 10 10 rectangle boa area . ! Az eremény: 100 (a metódus-kódöröklés működik)

Osztálykombinátorok és egyéb lehetőségek

A fent leírtakhoz képest még egyéb lehetőségeink is vannak, például egy tuple deklaráció után elhelyezett final szó esetén ha megpróbálunk származtatni az adott osztályból, akkor hibát kapunk és van még néhány apróbb különlegesség, de ami még fontos részét képezi a típusrendszernek az az lehetőség, hogy már meglévő osztályainkból létrehozzunk osztálykombinátorok segítségével: