A következő leírásban az alábbi implementációkhoz tartozik részletes dokumentáció:
A Smalltalk nyelv felépítésénél fogva mindig együtt jár egy fejlesztői környezettel. Program fejlesztése meglehetősen nehéz a környezet használata nélkül. Sőt, tovább bonyolítandó a fejlesztők életét, a nem szabványos, de általános használatra tervezett osztályok és metódusok más és más néven szerepelnek a különböző rendszerekben. Ebben a részben néhány ilyen fejlesztői környezet kerül bemutatásra.
Íme néhány az ismertebb Smalltalk környezetek közül:
Ezek közül kettővel, a Dolphin Smalltalkkal, és a Cincom Smalltalkkal foglalkozunk részletesen. A bemutatások saját tapasztalatokon alapulnak, ezért néhol nem teljesen objektívek.
A fejlesztői környezetek - sokszínűségük ellenére tartalmaznak hasonló komponenseket. Tipikus példa erre egy olyan ablak, amelyben a rendszer meglevő osztályait, és azok metódusait tallózhatjuk. Erre a feladatra minden környezetben szükség van, és az e célra biztosított ablakok is sok közös vonást mutatnak.
Egy normál grafikus Smalltalk környezet minimálisan az alábbi három ablaktípust adja a felhasználónak:
A Workspace általában egy pár speciális funkcióval kibővített szövegszerkesztő ablak. Itt megadhatunk programrészleteket, azokat vagy azoknak egy részét végrehajthatjuk, a végrehajtásnak megjeleníthetjük az eredményét. Az aktuális sorral vagy a kijelölt szövegrészlettel az alábbi funkciók hajthatók végre:
Ez olyan ablak, amely a rendszertől származó egyszerű szöveges üzenetek megjelenítésére szolgál. Általában a futtató rendszer használja, de a felhasználó objektumai is írhatnak rá.
Az Object-arts által kiadott implementációnak két változata van, a kereskedelmi Dolphin Professional és a Community Edition, ami ingyenesen regisztrálható nam kereskedelmi célokra. Az utóbbiban kevesebb funkció elérhető, például nem lehet a megírt programokból futtatható .exe állományt készíteni. Az alábbiakban a Dolphin Smalltalk X6 Community Edition kerül bemutatásra.
A Dolphin Smalltalk rendszere a Windows használói számára könnyen kezelhető. Áttekinthető ablakokat tartalmaz, jó keresőműveletekkel. A fejlesztői környezet minden pontján minden értelmes művelete pár kattintással elérhető. A rendszer egyik hibája, hogy nehezen viseli el a Windows nemzeti billentyűzet-kiosztását: néha teljesen önkényesen vált a kiosztások között.
Az osztálytallózója az itt bemutatott három implementáció között a legjobb. A Class Diagram segítségével megtekinthetjük az osztályok öröklődési hierarchiáját részletesebben. Az ablak felső fele három részre van bontva: balra az osztályokat öröklődési hierarchia szerint láthatjuk egy fában. Középen a kiválasztott osztály kategóriáit, protokolljait és változóit látjuk. Jobbra a metódusok jelennek meg. Lehet váltani példány- és osztálymetódusok megjelenítése között, új metódusokat definiálhatunk, törölhetünk, az egyes metódusoknak beállíthatjuk a láthatóságát valamint megnézhetjük, hogy a kódban hol hivatkoznak egy adott metódusra. Az ablak alsó felén is válthatunk a nézetek között: láthatjuk a kiválasztott metódus vagy osztály definícióját, az osztályhoz tartozó leírást, valamint az osztálykommentet.
A Workspace ablakában a Display It funkció végrehajtásakor kapott eredmény közvetlenül a kijelölt szövegrész mögött kerül beszúrásra. Még néhány funkció elvégezhető a kóddal:
A workspace a kijelölt rész végrehajtásakor szintaxiskiemelést alkalmaz. Az ablak képes RTF formátumú szöveg megjelenítésére.
A hibakereső ablak alsó részében mindig a végrehajtás alatt lévő kódot láthatjuk, és ki van jelölve a következő lépésben kiértékelendő kifejezés. A bal oldalon a hívási verem látható, Ennek általában csak a felső része érdekel, ugyanis tartalmazza az utolsó parancs kiadásától kezdődően az összes végrehajtás alatt álló metódust. A jobb oldalon pedig több dolog is látható: az aktuális objektum (az az objektum, amelynek a metódusa éppen végrehajtás alatt áll) leírása, és az összes példányváltozójának értéke, a lokális változók, valamint az adatverem. Az adatverembe az üzenetküldés argumentumai kerülnek, először a fogadó objektum, és utána a paraméterek.
A feltelepített Smalltalk rendszer és a fájlrendszer közötti átmenetet a csomagok fogalma adja. Egy projekt elemeit egy csomagba rakhatjuk, és ekkor együtt tudjuk őket kezelni. Új csomag létrehozásakor meg kell adni a hozzá rendelt fájlt.
A csomagok alapvető eleme az osztály. Minden osztály legfeljebb egy csomagba tartozhat (amelyik egybe sem tartozik, azt uncomitted-nek nevezik). Csomagokba tartozhatnak továbbá ún. laza metódusok (loose methods). Lazának nevezünk egy metódust, ha egy, a rendszerben lévő, de a csomaghoz nem tartozó osztály kiegészítése. A csomagok tartalmazhatnak továbbá globális változókat (amelyek a Smalltalk nevű SystemDictionary típusú objektum elemei), valamint erőforrásokat (részletesen lásd az erőforrástallózónál). Megnézhetjük továbbá a kiválasztott csomag függőségeit: mely további csomagok szükségesek a működéséhez.
Ha egy csomag telepítve van, akkor a csomaghoz tartozó fájl (mentések után) konzisztens a Smalltalk rendszerrel: pl. egy osztály módosítása a fájlban is jelentkezik. Ha a rendszerben létrehozunk egy új csomagot, akkor az automatikusan telepítettként lesz nyilvántartva. De mit tehetünk egy rendszeren kívülről érkezett csomaggal? Erre a feladatra tartalmaz a rendszer egy install és egy uninstall funkciót. Értelemszerűen az előbbivel kívülről érkezett fájlt tehetünk a rendszer részévé, az utóbbival pedig egy csomag tartalmát "vonhatjuk ki" a rendszerből. A csomagok tartalmazhatnak négy scriptet, (név szerint pre-install, post-install, pre-uninstall és post-uninstall) amelyek az installálás vagy uninstallálás előtt vagy után hajtódnak végre, lehetőséget adva ezzel a telepítés egyénivé tételére.
Háromféle csomagfájl-formátum létezik:
Itt kezelhetjük a rendszer által ismert protokollokat. Bal oldalt az ismert protokollok, középen a protokoll teljesítéséhez szükséges szelektorok halmaza, jobb oldalt pedig a rendszerben lévő és a kiválasztott protokollt teljesítő osztályok találhatók. Itt az adott protokollhoz "hozzáadhatunk" egy osztályt, ekkor a rendszer az osztályhoz legenerálja az összes szükséges, de hiányzó metódust.
A Dolphin Smalltalk rendszerben az erőforrás egy újrafelhasználható, grafikus felhasználói interfész-komponenst jelent. Az erőforrásnak mindig van egy tulajdonos osztálya (azon osztály, amelynek az erőforrás-objektum példánya), valamint egy neve, ami egy egyszerű string. Ez a kettő azonosítja egyértelműen az erőforrást. Egy erőforrás alapértelmezésben ahhoz a csomaghoz tartozik, amelyhez a tulajdonos-osztálya, de a "laza" metódusokhoz hasonlóan lehet "laza" erőforrásokat is készíteni: ekkor a csomagban lévő erőforrás tulajdonosa egy másik csomagban lévő osztály. Az erőforrások szerkesztése a View Composer ablakban történik.
Felmerül a kérdés, hogy mely osztály példányaként célszerű erőforrást létrehozni. Ennek kifejtéséhez egy kicsit nézzünk bele a Dolphin grafikus rendszerének működésébe. Ez a grafikus rendszer egy MVP-nek (Model - View - Presenter) nevezett keretrendszerre épül. Ebben az alkalmazás felhasználói felületének elemeit hatáskörük alapján három csoportba soroljuk:
A fentiek alapján látható, hogy a legtöbb erőforrás a View és a Presenter osztály leszármazottainak példánya. Az előbbihez tartozik például a GroupBox, PushButton, Toolbar különböző változatai, tehát általános célú UI elemek. Az utóbbihoz tartozik például a BooleanPresenter, amely logikai értékek különböző típusú megjelenítéséhez ad erőforrásokat (Yes-No felirat, jelölőnégyzet, kétállású nyomógomb stb).
A legtöbb fejlesztőeszköz biztosít egy keretrendszert, mely megkönnyíti az alkalmazások készítését. A mai programok grafikus felületei széleskörű kommunikációt biztosítanak a program és a felhasználója között, így kódjuk egyre bonyolultabbá vált. Egy keretrendszer előre elkészített osztályokat biztosít, amivel jelentősen leegyszerűsíti a programozó dolgát. A Dolphin Smalltalk egy egyedi keretrendszert tartalmaz, a Model-View-Presenter (MVP) Framework-öt. Az MVP egy komponens alapú rendszer, ahol a komponenseket három egymással együttműködő osztály alkotja: a model, a view és a presenter.
Sok szempontból hasonlít más komponens alapú rendszerekhez, de nagy fokú
rugalmassága eltérővé teszi riválisaitól. Természetesen emiatt a rendszer is
bonyolultabbá vált, ami nehezen elsajátíthatóvá teszi a használatát.
Bár a Dolphin Smalltalkot természetesen olyan alkalmazások készítésére is
lehet használni, melyeknek alapja nem az MVP, de azt fogjuk tapasztalni, hogy
a Dolphin minden fejlesztőeszköze erre a keretrendszerre épül.
Az MVP alkalmazás létrehozásának javasolt menete teljesen a fordítottja az ismertebb fejlesztőrendszerekben, pl. Visual Basicben megszokottnak, ahol legtöbbször az alkalmazás "látható része" az, amit elsőként megvalósítunk. Az MVP rendszerében leggyakrabban először a modelt hozzuk létre, ez lesz az alkalmazásunk bázisa. Miután a modelünk legalább részben elkészült, a presenter-osztályok tervezésével folytathatjuk a munkát, amik a user interface és a model közötti kommunikációt irányítják. Csak ezután (vagyis legvégül) fogunk hozzá, hogy elkészítsük a view-t, azaz a grafikus felhasználói felületet. Ezt a tervezési folyamatot többször is megismételhetjük, mire a végső designt megkapjuk. Ezt nyilván úgy érdemes csinálni, hogy minden egyes szinten csak annyit dolgozunk, amennyi feltétlenül kell a változtatások teszteléséhez. Így ciklikusan, darabokból rakjuk össze az alkalmazásunkat.
Model
A model tárolja az alkalmazás adatait, és biztosítja a műveleteket
, melyeken keresztül azok elérhetők. Egy model
osztály nem feltétlen kell, hogy támogasson előre definiált üzeneteket, ezért
nem is szükséges, hogy a model osztályt egy különleges ősosztályból
származtassuk. A Dolphin osztályhierarchiája mindenesetre rendelkezik egy
Model osztállyal, ami (ha ezt választjuk) megfelelő szülő lehet. A
Model osztályt azért is érdemes ősosztálynak választani, mert az közvetlenül
implementálja a #setEvents és a #getEvents üzeneteket, és ezáltal hatékony
esemény-kiváltó mechanizmushoz férünk hozzá. Ami nagyon hasznos, mivel a Model
eseményeket kell, hogy kiváltson ahhoz, hogy kommunikálni tudjon a presenterrel
és a view-val.
A model nem kapcsolódik a felhasználói felülethez (UI). Ez teszi lehetővé,
hogy újra felhasználjuk olyan szituációkban, amikben teljesen mások az
UI-elvárások. A model tehát nem tud közvetlenül sem a view sem a presenter
létezéséről. Ez azzal a következménnyel jár, hogy a model osztály soha nem
rendelkezhet olyan példányváltozóval, ami referenciát tárol a presenterre, a
viewra vagy egyéb más UI-objektumra. Ezért lesz majd szükségünk arra az
esemény-kiváltó mechanizmusra, amit már részben említettünk, és később még
látni fogunk.
Példa: tekintsük a SmalltalkSystem-et, ami egy model osztály. A Dolphin magát a fejlesztő rendszert reprezentálja vele. Olyan metódusokat tartalmaz, amiket a fejlesztőeszközök használnak számos művelet végrehatásához, és a legtöbb eszköz ennek az osztálynak a singleton példányát alkalmazza saját modelként.
View
A view tulajdonképpen egy ablak, ami azért felelős, hogy a felhasználó számára megjelenítse a model adatait. Ez tipikusan (de nem feltétlenül) egy Windows control. A fenti képen a model és a view közötti piros nyíl egy indirekt kötést jelképez, ami úgy valósul meg, hogy a view a model Figyelője, azaz ha valami változás történik a modelben, akkor a Figyelő, mint objektum is változik, hiszen a viewban is meg kell jelennie a módosításnak. Ahogy fent már említettük, a model nem tartalmazhat közvetlen referenciát a viewra, de hogy értesítse a Figyelőt a változásról, figyelmeztető eseményt vált ki a #trigger: használatával. A view már korábban figyel erre az eseményre ( erre jó a #when: ), és ha az esemény kiváltódik, akkor a megfelelő metódus használatával megkapja az új adatot, amit aztán a felhasználó rendelkezésére bocsát. Tehát alapvetően a két osztály kapcsolata az MVP-ben úgy néz ki, hogy a view tudja, hogy melyik model tartozik hozzá, de megfordítva ez már nem igaz. Ami a presentert illeti, a viewnak a presenterre is közvetlen példányváltozója van.
Presenter
Míg a view azért felelős, hogy az output eljusson a felhasználóhoz, a
presenter dolga az, hogy az inputnak megfelelő reakcióra késztesse a modelt. Ha
a felhasználó leüt egy billentyűt, mozgatja az egeret stb, akkor az ezekből
adódó információkat a view kapja meg, majd a presenternek továbbítja azokat. A
presenter meghatározza a modelben, hogy melyek az aktuális adatok, amin a
változtatásokat el kell végezni.
Láthatjuk, hogy a presenter jelentősége abban áll, hogy ő a közvetítő a model
és a view között.
A presenter tervezésekor arra érdemes gondolni, hogy számos egyéb presentert
hozunk majd létre, amik mind-mind az aktuális modelünkkel fognak együttműködni.
(ui.: a presenter (és a hozzá kapcsolódó view) egy hozzáférési módot ad a
felhasználónak a modelhez, de esetleg más körülmények között majd nem ez tűnik
a legcélszerűbbnek, és ezért pl. egy másik UI-ről szeretnénk gondoskodni. )
Nyilván, mivel a view és a presenter figyel bizonyos eseményeket, amiket a hozzájuk tartozó model generálhat, nem lehet a viewt vagy a presentert csak egyszerűen egy modelhez hozzácsapni, és azt várni, hogy működjenek. A model osztály fogalmát úgy jellemezhetjük, mint üzenetek egy protokollját, amire válaszolnia kell, illetve azon események protokollját, amiket kivált. Nevezzük ezeket rendre in-protokollnak és out-protokollnak. Fontos tehát, hogy csak a megfelelő viewt és a megfelelő presentert tegyük hozzá a megfelelő modelhez. Például a ListBox és a ListPresenter osztályok egy "lista típusú" modelt várnak a megfelelő in- és out-protokollal, például a ListModel osztályt.
Általában, és nem ok nélkül, csak olyan model, view és presenter objektumokat használjunk együtt, amiket eleve úgy terveztünk, hogy egymással együtt tudjanak működni. Fontos, hogy milyen nagy a model, a view és a presenter kommunikációjának a költsége, azaz az in- és az out-protokollok mérete, hiszen ez pontosan a rugalmasság rovására növelhető csak. Minél egyszerűbbek a protokollok, annál rugalmasabb, könnyebben cserélhető elemeket kapunk.
Komponens alapú architektúra
Minden MVP-hármast tekinthetünk egy komponensnek, amit később újra fel tudunk használni, ha összetett komponenseket akarunk készíteni, amiket aztán tovább használhatunk még összetettebb komponensek készítésénél. Valójában ez a három elemből álló blokk nagyon hasonlít az ismert komponens alapú architektúrákhoz, mint például az ActiveX vagy a Java Beans. Egyszerűvé válik egy bonyolult alkalmazás elkészítése, ha egy komponens alapú architektúrát használunk, hiszen számos komponenst rakhatunk könnyedén egybe, és nem igényel különösebb programozói erőfeszítést az sem, hogy ezeket egymással együttműködővé tegyük.
A Dolphin MPV-komponensei is megengedik ezt, de ennél többet is tudnak,
hiszen a komponensen belül az egyes elemeket önállóan is kicserélhetjük egy
másikra, ha arra van szükségünk. Ezáltal lehetőségünk van rengeteg új komponens
létrehozására egyszerűen csak a különböző model, view és a presenter elemek
kombinálásával. Ez nagyon nagy szabadságot jelent, de a különböző kombinációk
megalkotásánál nyilván valamennyire meg van kötve a kezünk, mint ahogy ezt már
a fenti Megjegyzés részben láttuk.
Miért éppen Figyelő?
Eddig csak olyan esetekkel foglalkoztunk, ahol egy view tartozott egy modelhez. Felmerülhet ezért az a kérdés, hogy miért szükséges, hogy a view a model Figyelője legyen, hiszen ez egy költséges esemény-kiváltó mechanizmust eredményez, ami nyilvánvalóan sokkal bonyolultabb, mint egy közvetlen kapcsolat létesítése. Nézzük meg, hogy melyek azok az előnyök, amik miatt mégis a Figyelőt használja az MVP!
Osztott modelek
Tehát a Figyelő használatának az előnye az, hogy az egyes MVP-komponenesek
osztozhatnak a model adatain.
Normál szituációban a presenter hozza létre és kapcsolja önmagát a default
modelhez, igy azt gondolhatjuk, hogy ő ténylegesen birtokolja a model-adatot.
A legtöbb tervben ez elfogadható. Előfordulhat azonban, hogy két presentert
akarunk használni arra, hogy ugyanazokon az adatokon dolgozzanak, és ha az
egyik változtatásokat végez az adatokon, akkor a másik is frissüljön. Ahhoz,
hogy ezt elérjük, mindkét presenternek egy külön-külön létrehozott modelhez
kell kapcsolódnia, vagy az egyik presenter megoszthatja a saját modeljét a
másikkal.
Ebben a szituációban mindkét view módosul a model adatainak változásával,
függetlenül attól, hogy ezeket a változtatásokat a másik view vagy valamelyik
másik komponens hajtotta-e végre.
Hogy jobban megértsük ezt, ki lehet próbálni a következő példát. Érdemes az
egyes sorokat külön végrehajtani.
m := false asValue.
BooleanPresenter showOn: m.
BooleanPresenter show: 'Push to toggle' on: m.
BooleanPresenter show 'Yes-no text' on: m.
Egyszerű és összetett MVP-komponensek
Két teljesen különböző MVP-komponens típus van, amivel találkozni fogunk. Az egyszerű MVP-komponensben egyetlen model kapcsolódik egyetlen presenterhez és egyetlen view-hoz. Egy ilyen hármasra, mint amilyen a képen is látható, gondolhatunk úgy, mint egy elemi komponensre, amiből aztán az összetett komponensek felépíthetők.
Egy ilyen egyszerű komponens pl a TextPresenter. Itt a default
model egy ValueHolder, ami egy Stringet rejt, és a default
view egy TextEdit.
Az összetett MVP-komponensben egy komplex modelt kapcsolunk egy összetett
presenterhez és view-hoz. Amikor a modelt hozzákapcsoljuk az összetett
presenterhez, gyakran sok kicsi almodelnek tekintjük, amiket egymástól
függetlenül kapcsolunk hozzá alkalmas alpresenterekhez és alview-khoz. Az
eredmény tehát egy hármas, ami alhármasok hierarchiájából épül fel.
Jó példa az összetett komponensre a MethodBrowser. A MethodBrowser modelje a SmalltalkSystem singleton példánya. A view egy összetett view, ami a View Composerrel készült. A ListPresentert (ami egy Listmodelhez kapcsolódik) arra használjuk, hogy a metódusok listáját megjelenítse, amiket keresünk, a metódusok forrásszövegét pedig a SmalltalkWorkspace presenter jeleníti meg.
A Cincom cég terméke szintén kereskedelmi program, azonban ingyenes változathoz is hozzá lehet jutni. Itt az ObjectStudio 6.8 kerül bemutatásra.
A telepítésnél rögtön nehézségek adódnak: az ingyenesség ellenére a nem üzleti felhasználóktól is egy, a honlapon történő regisztrációval megszerezhető kódot kér a telepítő. Ettől nem kell megijedni, egyszerűen kattintsunk (a Next vagy a Cancel helyett) a jobb felső sarokban az ablak bezárása gombra. Ekkor elindul a telepítés. (A cég honlapján történő regisztráció után semmi nem történt, semmiféle visszajelzés nem érkezett.) A program minden indítása után mindig újra kéri a licencszerződés elfogadását.
A Dolphin rendszerben megszokottnál jóval kevesebb eszköz áll rendelkezésre. Az beépített osztályok készítői nem fordítottak elég figyelmet a könnyű újrafelhasználhatóságra, a legtöbb osztálynál és metódusnál hiányzik a megjegyzés, vagy ahol van, ott is kevés. A rendszer beépítve kevés protokollt támogat, ez is megnehezíti a metódusok között kereső felhasználó dolgát.
Az osztálytallózójában pozitívum, hogy a metódusok megjelenítésénél tetszőleges ősosztály kiválasztható, és csupán ezen ősosztálynak és leszármazottainak metódusai láthatók. Az osztályok alapértelmezésben ABC-sorrendben vannak feltüntetve, az eszköztár List/Tree view ikonjával válthatunk fastruktúrájú nézetre. Egy osztály adatainak megjelenítése viszonylag egész hosszú ideig (gyakran fél másodpercig) tart. Nagy hiánya, hogy nem lehet egy teljes osztály kódját File Out művelettel exportálni.
A munkaterület nagyban eltér a korábban használttól. Az első különbség az, hogy ha nincs kijelölve kódrészlet, akkor nem az aktuális sor, hanem az ablak teljes tartalma végrehajtásra kerül. A végrehajtható parancsok is különböznek pár apróságban:
Mindent egybevetve a a rendszer nehézkesebben használható mint a korábban látott rendszeré. Hiányoznak a gyorsbillentyűk, a Browse It, Debug It funkciók, valamint a kiválasztott objektum helyi menüből elérhető, mindenre kiterjedő eszközkészlete. Hibakeresésre töréspontokat használhatunk, amelyekkel gyakran használt osztályok esetén nehézségeink adódhatnak.
A fenti hibák és hiányosságok ellenére az ObjectStudio tartalmaz egy olyan szolgáltatást, amely nagyon hiányzik a korábban bemutatott rendszerből (igaz, annak Professional csomagjában állítólag szerepel). Ez pedig a Program Generator. Ez készít az ostudio.exe fájlról egy másolatot, amely a saját nevével megegyező .img (osztályok adatait tartalmazó fájl) fájlt fogja betölteni. Ezt az image-fájlt pedig úgy állítja elő, hogy a kiválasztott alkalmazás (application) által használ osztályok maradjanak csak benne, és indításnál nem az ObjectStudio ablakát, hanem az alkalmazás ablakát nyitja meg. Tehát lényegében a Smalltalk alkalmazásból egy futtatható, önálló programot állít elő.
GNU Smalltalk egy olyan implementáció, mely szorosan követi a Smalltalk-80 szabványt, így nem ismételjük meg a már az általános leírásban elhangzottakat.
A következőkben sorra vesszük a GNU Smalltalk 1.1.1-es verzió tulajdonságait, és foglalkozunk a Smalltalk-80 szabványtól való eltéréseivel.
GNU Smalltalk támogatja a következőket:
Ez az opció egy pillanatfelvételt készít a GNU Smalltalk Virtual
Machine aktuális állásáról. Ez azt jelenti, hogy az összes objektumot lementi,
hogy egy későbbi időpontban betölthessük őket.
Erre két üzenetet használhatunk:
Ez a GNU Smalltalk rendszer aktuális állapotát egy 'mst.im' nevű fájlba
menti. Amikor később elindítjuk a GNU Smalltalkot, ezt a fájlt fogja betölteni a binárisba, amennyiben
egyik kernel fájl sem tartalmaz frissebb fájlmódosítási dátumot, valamint ha a GNU Smalltalk verziószáma ugyanaz,
mint az image fájlt kreáló verziószáma, és ha az objektumtábla mérete nem változott az image fájl elkészítése
és betöltése közötti időben. Megjegyezzük, hogy a fogadóobjektum osztálya a 'SystemDictionary'; a gyakorlatban az
üzenetet a 'SystemDictionary' egy egyedének küldjük.
Ez az üzenet hasonlóan viselkedik, mint az előző, kivéve, hogy a string argumentummal megadhatjuk az image fájl nevét. Azonban a betöltéshez a program mindig az 'mst.im' fájlt fogja használni, ezt nem változtathatjuk. Ez az üzenet tulajdonképpen lehetőséget biztosít több pillanatát is tárolni a bináris fájlnak, és a betölteni kívánt mentett állapotfájl nevét csupán 'mst.im' -re kell átneveznünk, hogy használhassuk.
Javítja a teljesítményt azáltal, hogy kiküszöböli a leállásokat a szemétgyűjtés futása alatt. Üzenetet ír ki a program, ha
a garbage collector elindul, de ezt az alábbi beállítással kiiktathatjuk:
    Smalltalk gcMessage: false
Ez a mód segít a Smalltalk műveletek definícióját szerkeszteni. Később lesz még róla szó.
Ebben a szekcióban foglalkozunk azokkal a jellemzőkkel, melyek specifikusan a GNU Smalltalkhoz
lettek írva: C függvények hívásával Smalltalkból, a UNIX környezeti változóinak elérésével, és a
fordítás és futtatás különböző szempontok szerinti nyomkövetésének vezérlésével.
Ahhoz, hogy hívhassunk C függvényt, először informálnunk kell a Smalltalkot azokról a C
függvényekről, melyeket el szeretnénk érni. Ezt két lépésben kell megtenni:
Az összes metódust, amit Smalltalkból hívni akarunk, muszáj itt és így meghatároznunk.
A következő, amit tennünk kell, hogy meghívjuk ezeket a C függvényeket, és leírjuk az
argumentumaikat a Smalltalk futásidejű rendszerének. Nézzük a két függvény definícióját
('CFuncs.st'-ből kimásolva):
    Ez mondja, hogy mi egy system nevű C függvényt definiálunk. A névnek PONTOSAN egyeznie kell az initCFuncs-beli defineCFunc rutinnal.
withSelectorArgs: 'system: aString'
    Ez definiálja, hogy hogyan kerül a metódus a Smalltalkból meghívásra. A metódus nevének nem kell egyeznie a C függvény nevével;
Nekünk csak egyszerűen definiálnunk kell, hogy a szelektor legyen rambo: fooFoo; gyakorlatban hasznos lehet, ha a metódus neve megegyezik, míg az argumentum nevek utalnak azok adattípusára.
forClass: SystemDictionary
    Specifikálja, hogy az új metódus hol legyen tárolva. A mi esetünkben a metódus a SystemDictionaryben lesz elhelyezve, így az alábbi módon tudjuk hívni:
               Smalltalk system: 'lpr README'
    Nincs különösebb jelentősége, hogy melyik osztály fogadja a metódust; lehetne Float akár, de túlságosan is különösen néz ki, hogy ezt látni lehessen:
               1701.0 system: 'mail sbb@eng.sun.com'
returning: #int
    Ez adja meg a visszakapott elem C adattípusát, mely az ennek megfelelő Smalltalk adattípussá konvertálódik. Visszatérési típusok az alábbiak lehetnek:
    Szimbólumok egy tömbje, mely az argumentumok típusát tartalmazza sorrendben. Például, hogy hogyan specifikáljuk az 'open' hívást:
            args: #(string int)
    A következő argumentumok támogatottak:
    A paraméter konverzió táblázata:
File-IO üzenetek
A következő metódusokat definiálták a FileStream osztályban:
open: fileName mode: fileMode
    Visszatérési értéke: a FileStream osztály egy objektuma. A fileName-ben
(Stringgel) megadott fájlhoz nyújt hozzáférést a fileMode-ban megadott módon (amely szintén
String típusú, és pl.: 'fopen' metódusnál 'r', 'w', stb. értékű lehet).A stream elemei a
karakterek lesznek.
close
    Az adott FileStream-et lezárja. Bármilyen egyéb fájl streamnek küldött
üzenet hibás, és nem definiált cselekvést vált ki.
next
    Egy Character típusú objektummal tér vissza, mégpedig a stream soron következőjével.
nextPut: aChar
    Streamre küldi a (Character típusú) karaktert, mely a legutóbb fogadott karakter mögött letárolja azt.
position: bytePosition
    Átállítja a fogadó aktuális pozícióját a bytePosition értékre, melyet a fájl eleji 0 pozíciótól számít.
position
    Az aktuális pozícióját adja vissza egy integer számmal.
contents
    Visszatérési érték egy String, mely megmutatja a FileStream teljes hátralévő tartalmát.
atEnd
    true értékkel tér vissza, ha a FileStream objektum a fájl végénél jár, különben false-szal.
size
    Ha ismert, akkor visszaadja byteban az adott FileStream objektum méretét.
A system üzenet
A 3 UNIX fájl, az stdin, stdout és stderr deklarálva vannak, mint a FileStream globális egyedei.
Továbbá, az Object osztály definiál két újabb metódust:print és printNl. Mindkettő egy printOn: to stdout
üzenetet küld, a különbség csupán annyi, hogy a printNl a kiíratott érték utánra berak egy soremelést.
Ez az üzenet meghívja a rendszer system parancsát aString paraméterrel. Visszatérési érték egy integer, attól függően, hogy a system mit válaszol.
A getenv üzenet
Ez az üzenet meghívja a rendszer getenv parancsát az aString-re. Visszatérési érték vagy egy string, vagy nil, ha nincs környezeti változó aString névvel.
Blokk inicializálás
Ez az üzenet hozzácsatolja a rendszer Init block részéhez az aBlock
inicializálást. Az Init blockok a bináris image fájl v. kernel fájlok
betöltődése után hívódnak meg. Az aBlock -nak egy argumentum nélküli blokknak
kell lennie.
A fileIn: FileStream osztálynak küldött üzenettel (melynek egy fájlnév a string argumentuma) tudunk a Smalltalkba fájlt betölteni.
Például:
FileStream fileIn: 'foo.st' betölti a 'foo.st' fájlt a GNU Smalltk programba.
A GNU Smalltalk lehetőséget biztosít, hogy bizonyos üzenetek küldésével
közvetlenül elérhessük a memóriát. Byte vagy 32 bites szó szinten tudjuk
kezelni azt. Lehetőségünk van olvasni és írni a memóriát. Az GNU Smalltalkbeli
Integer korlátainak köszönhetően, szó szintű akcióknál csak 31 biten tudunk
dolgozni.
Ezen felül megkaphatjuk egy objektumunk memória címét, lejjebb részletesen írunk róla.
A két alaposztály, amiknek az üzenetet küldjük, a ByteMemory és a WordMemory. Ezen osztályok metódusai a következők:
ByteMemory class at: address
    A címet Integer-rel megadva, visszakapjuk az adott helyen levő byte-ot, mint Integer-t.
ByteMemory class at: address put: value
    Az adott címen levő byte-ot átírhatjuk egy 0 és 255 közötti számmal.
WordMemory class at: address
    A címet Integer-rel megadva, visszakapjuk az adott helyen
levő részét a memóriának Integer-ként. Függ a rendszertől, lehetséges hogy meg
van szabva, hogy a cím 4 többszöröse lehet csak. Megjegyzés: Ez a metódus nem
minden architektúrán működik (pl. VAX-on nem).
WordMemory class at: address put: value
    Memóriába beleírja az Integer értékét az address helyen. Ugyanazok a megjegyzések élnek itt is, mint az előző metódusnál.
Bigendian
    Egy globális változó, mely true értékre van állítva azokon
az architektúrákon, melyeknek 32 bites integer legjelentősebb byte-ja az alsó
címen van(pl.: 68000 és Sparc), míg hamis értékre van állítva, ha a legkevésbé
fontos byte van a legalacsonyabb címen(pl.:VAX).
Az alábbi metódusokat használhatjuk, hogy megkeressük egy objektum memóriacímét, vagy az ő OOP táblás helyzetét:
Memory class addressOfOOP: anObject
    Visszatérési érték: az anObject objektumhoz tartozó OOP címe Integer típusban, amely a program futása során nem változik.
Memory class addressOf: anObject
    Az objektum memóriabeli címével tér vissza. Fontos megjegyezni, hogy ez a cím csak a következő Garbage Collection-ig érvényes, így használata veszélyes lehet.
    Ez a metódus irányítja, hogy a bytekódok interpreter
processzként ki legyenek-e írva vagy sem. Pontosan ugyanazt érjük el, mintha a
parancssort -e -re váltanánk, de a metódus lehetőséget biztosít a nyomkövetés
nagyon finom irányítására. true értékkel kapcsoljuk be a kiíratást, false-szal
kapcsoljuk ki.
    Amennyiben az SystemDictionary executionTrace: előzőleg true
üzenetet kapott, azaz él a kiíratás, és elküldjük a SystemDictionary
verboseTrace: true üzenetet is, kiiratjuk a Smalltalk verem legfelső elemét.
    Ez az egyszerű metódus hívja meg a C debug parancsát.
Következő módon lehet használni: a Smalltalk metódus futásának egy pontján
szerzünk egy dbx-hez (üres rutinhoz) vagy gdb-hez hozzáférést. Ezt általában
nem egyszerű megcsinálni. A GNU Smalltalk rendszerben a C debug rutin hívása
önmagában szerepel, így helyezzünk el megállási pontokat (breakpointokat) benne
a debuggerből. Tegyük a C debug rutint abba a C függvénybe, melyet debuggolni
akarunk.
Tehát ha rakunk egy breakpointot a 'debug' rutinba, és meghívjuk a debug
metódust pont mielőtt ahhoz a kódhoz érkezünk, amit debuggolni akarunk,
részletes debuggolás kontrollálás lehetőséget tudhatunk magunkénak.
    Ezzel az egyszerű paranccsal engedélyezhetjük vagy
iktathatjuk ki az interpreter műveletek alatti C profil információ generálást.
Ha true argumentumot küldünk, akkor későbbiekben lehetőségünk van a 'gprof'
nevű programmal analizálni a fordítás alatt történteket.
    Lehetőséget biztosít ez az üzenet arra, hogy ki- illetve bekapcsoljuk a szemétgyűjtő által végzett munka kiíratását. Alaphelyzetben ez az opció true-ra van állítva.
    Ezen metódus meghívása azonnali és feltétel nélküli kilépést eredményez a GNU Smalltalkból.
    Különböző implementációkkal való kompatibilitás érdekében a
GNU Smalltalk felkínálja a := használatát, azonban ügyelni kell arra, hogy
mindkét oldalán legyen egy-egy space legalább, különben hibát kapunk.
A cím magyarázásra szorul. A Smalltalk-80 leírása a Adele Goldberg és David
Robson által írt Smalltalk-80: the Language and its Implementation című
könyvben jelent meg, melyet manapság Kék Könyvként szoktak emlegetni.
Tehát az alábbiakban felsoroljuk a GNU Smalltalknak a Smalltalk-80 szabványtól való eltéréseit:
Ebben a pontban beszélünk az Emacs móddal, mely eszközöket kínál az interaktív kommunikálására a Smalltalk rendszerrel egy Emacs ablakon keresztül.
Az Emacs képes automatikusan Smalltalk módba átállni, ha az ember egy
Smalltalk fájlt szerkeszt (legalábbis egy '.st' kiterjesztésű fájlt). Ehhez az
alábbi sorokat kell a .emacs fájlba másolni:
Ez a beállítás természetesen akkor működik jól, ha a Smalltalkunkat a fenti könyvtárstruktúrába telepítettük, különben az elérési út változtatásra szorul.
Amennyiben növelni szeretnénk a sebességét a szerkesztőnek, fordítsuk le az 'st.el'-t bájtkóddá, majd változtassuk meg az elérési út végén szereplő fájl nevét 'st.elc'-re.
Az is egy jó ötlet, ha a GNU Smalltalk könyvtárat is berakom az EMACSLOADPATH környezeti változóba.
A GNU Smalltalk "editing mode" segítséget nyújt a kódunk szerkesztésénél.
Mióta a Smalltalk szintaxis erősen környezetfüggő, előfordulhat némi zavar a szerkesztési módban, ha éppen egy kifejezést írunk a metódus definíciók közben. Különösen lokális változók használatakor:
Itt például a második "|" jel lehetne bináris operátor egy második foo
argumentummal. Ha elveszni érezzük magunkat ehhez hasonló kifejezések írásánál,
tegyünk átmenetileg a kifejezés elé egy "idióta" metódusnevet - melyet
távolítsunk el, mihelyst készen vagyunk a kód szerkesztésével -, így:
Vigyük a kurzort arra a sorra, amely a self inspect-et tartalmazza.
Nyomjunk C-c c-t. Semmi nem fog előbukkanni a Smalltalk ablakban, de ennek
ellenére mégis lefordult a BlockContext>>callers metódus. Hogy kipróbálhassuk,
gépeljük be az alábbi kódot:
mely egy szimpla hívóverem visszamásolást eredményez.
A C-c c parancs egy egyszerű heurisztikát használ, hogy meghatározza a
metódusdefiníció határait. Általában, mikor változtatunk a metódusdefiníción,
nyomunk egy C-c c -t és odamegyünk ahhoz, ami következik. Amikor azonban
fordítani akarunk egy egész csokor metódusdefiníciót, ki kell jelölnünk,
melyikekre gondolunk, és C-c e-t kell használnunk.
Miután lefordítottunk és futtattunk pár kifejezést, szükségünk lehet egy
mentésre a munkánkról, hogy legközelebb ne kelljen ezt mind megcsinálnunk.
Ehhez használjuk a C-c s parancsot, mely kreál egy Smalltalk bináris image-t,
melyet 'mst.im' fájlba rakja. Ha egy prefix argumentummal hívjuk meg ezt a
parancsot, megadhatunk nevet az image fájlunknak, és be is állíthatjuk a -I
flaggel, hogy legközelebb ez legyen a Smalltalk elindításakor automatikusan
betöltődő image.
Kifejezés kiértékelése után az eredményt kiírathatjuk a C-c p paranccsal.
Jelöljük ki a kívánt területet, majd használjuk ezt.
Egy fájl
behívásához használjuk a C-c f parancsot. A promptnál begépelhetjük a behívandó
fájl nevét, vagy csak simán nyomhatunk Entert is, és ebben az esetben az
aktuálisan a bufferben levő fájl fog betöltődni a Smalltalkba.
Amennyiben úgy döntöttünk, hogy kilépünk a programból (ami azért néha napján
előfordul), üssünk C-c q -t. Ha be akarjuk izzítani ismét a Smalltalkot, vagy
netalántán meghalna alattunk a program, akkor használhatjuk a C-c m parancsot,
és a Smalltalk reinkarnálódik. Amennyiben fut a Smalltalk, csak az ablak nem
látható, ugyanezzel a paranccsal tudjuk előcsalni.
Ezen verziója a GNU Smalltalknak (1.1.1) egy szimpla interfésszel jelent meg
az X-hez. Ez jelenleg közvetlen kapcsolatban van az X protocol layerrel az
Xlibnél is alacsonyabb szinten. Mit kínál számunkra, mindamellett, hogy a
legtöbb objektumorientált keretkörnyezet Xlib objektumokkal
kommunikál?!
STIX egy kezdeti szelete a Smalltalk és az X közötti interfésznek. Tervezve
van, hogy használható apró dolgokkal egészüljön ki, de még sok ember közös
munkája szükségeltetik ehhez.
Azért hogy azt is érzékeltessük, mi az, amit
már most tud: implementálva lett a Kék Könyvben szereplő Pen osztály, mellyel
tudunk rajzolni.
Futtatását ezen dokumentum keretein belül nem taglaljuk.
A legtöbb Windows változat alá elérhető a GNU Smalltalk bináris telepítőfájlja.
A korábbi Linux disztribúciókhoz elérhető volt egy smalltalk csomag, amely a telepítés után lefordította az aktuális környezetet, az újabbakból azonban kompatibilitási okokból ezt már kihagyják, így a fordítást nekünk kell elvégeznünk. A forrásfájlok megtalálhatóak a GNU Smalltalk honlapján.
A fordításhoz sok csomag szükséges. Ezek egy része az aktuális verzióval jelölve található meg a csomagkezelőben, ezeknél a csomag neve mellett a jelenleg elérhető változat neve is megtalálható. A teljes keretrendszer minden funkciójához szükséges csomagok (apt):
A fordításhoz csomagoljuk ki a forrásfájlokat. (Ügyeljünk rá, hogy az elérési út nem tartalmazhat szóközt, vagy egyéb escape-elendő karaktert.) Álljunk a gyökérkönyvtárba, majd adjuk ki az alábbi parancsokat:
./configure
make
A különböző disztribúciókon számtalan hiba felléphet fordítás közben. Ezek közül az egyik leggyakoribb a libc.la fájllal kapcsolatos. A fájl eltávolítása, majd a make újrafuttatása általában megoldja a problémát.
A sikeres fordítást ellenőrizhetjük a make check paranccsal.
Ha az ellenőrzés sikeres, root-ként adjuk ki a make install parancsot, pl.
sudo make install
Ezután már indítható a három telepített eszköz valamelyike:
A környezet parancssorból (terminálból) a gst paranccsal indítható. Ezzel egyből az értelmezőben találjuk magunkat, hasonlóan pl. a Haskellhez írt ghci-hez. A beírt parancsok egyből le fognak futni. A konzolra író üzeneteknél a forrásobjektum is kiírásra kerül, így pl. ha a HelloWorld objektummal kiíratjuk, hogy HelloWorld, akkor a kimenet HelloWorldHelloWorld lesz, amiből az első a szöveg, a második az objektum. Egyéb esetekben ez persze egyértelmű:
Komolyabb fejlesztéshez már érdemes valamelyik grafikus fejlesztőkörnyezetet használni.
A fejlesztőkörnyezet parancssorból (terminálból) a gst-browser paranccsal indítható. Látható, hogy az ablak kettő, illetve öt részre van felosztva. Felül, egymás mellett találhatóak a névterek, a kijelölt névtérben található osztályok, a kijelölt osztályhoz tartozó metóduskategóriák, illetve a kijelölt metóduskategóriába tartozó metódusok, lent pedig egy szerkesztő.
Futtatáskor természetesen a kimenetet is szeretnénk látni. Ehhez a Tools menüből válasszuk a Bottom Pane menüpontot, vagy nyomjuk meg az F4 billentyűt. A Transcript fülön látható a standard kimenet, míg a Workspace fülön fut az interpreter, melyet a parancssoros környezetből már megismertünk.
A Smalltalk-80 néhány szülőatyja érezte először szükségét egy teljesen objektumorientált, maximálisan hordozható, de a Smalltalknál szabadabb és kezelhetőbb fejlesztői környezetnek, mely jó néhány multimédiás lehetőséget is támogat, ezáltal pótolva a Smalltalk hiányosságait. A Squeak egy önálló Smalltalk amelyben egy kutató, professzor vagy egy érdeklődő diák egyaránt tanulmányozhatja a rendszer bármely részének forráskódját, és megváltoztathatja azt, csupán Smalltalk tudásra lesz szüksége. Beépített könyvtári elemekkel nagymértékben leegyszerűsített módon kezelhetnek képet, hangot, hálózati eszközöket, webes tartalmat.
A Squeak egy jól hordozható, nyílt
forráskódú grafikus Smalltalk-80 implementáció, melynek virtuális gépe teljes
egészében Smalltalkban íródott, ezáltal könnyű azt módosítani, elemezni, vagy
hibát keresni benne. A hatékonyság (és sebesség) növelése érdekében a fordító
azonos C kódot állít elő, így közelítve meg egy Apple Smalltalk implementáció
teljesítményét. Tulajdonképpen egy Smalltalk alapokra épített grafikus felület,
ebből következően az egerünkre fontos feladatok hárulnak. :o)
További
figyelemreméltó tulajdonságai:
Minden verzió tartalmazza a platform-független szín-, hang- és hálózatkezelést, valamint a teljes forráskódot. Eredetileg Apple Macintosh -on fejlesztették, azonban azóta sok-sok különféle platformra transzformálták, a világ Squeak fejlesztői. Többek között a következő operációs rendszerek alatt létezik a környezet:
Példaként a környezet hordozhatóságára, ez egy
kézi-számítógépen futó Squeak:
A név maga többek között az egércincogás hangutánzó szava az angol nyelvben. Nem találtam rá információt hogy miért is erre esett a választás. Az oldal elején, valamint a főbb fejezetek címe előtt a Squeak hivatalos logója, egy egérfej látható.
1995 decemberében Dan Ingalls, Ted Kaehler, John Maloney, Scott Wallace es Alan Kay az Apple Computer-nél úgy gondolta hogy szüksegük lenne egy olyan fejlesztőkörnyezetre amely használható és programozható nem műszaki, nem hozzáértő emberek, sőt gyerekek által is. Egy maximálisan platformfüggetlen, mindenféle multimédia támogatással ellátott szoftvert szerettek volna. Éppen ezért rendszerük alapjául egy kicsi, hordozható magot szántak, amely egyszerű és uniformizált, mely gyorsan adaptálható mindenféle eszközre. Felmerült a Java alkalmazásának gondolata is, de akkoriban az még kiforratlan állapotban volt, legfőképpen a hozzátartozó könyvtárrendszer.
Mindemellett a Smalltalk implementációk pedig nem adták meg azt a szabadságot amelyre az alkotók vágytak. Korlátokba ütköztek volna az elképzelt grafikai, és multimédiás megoldások, az egyszerű hálózati hozzáférés megvalósítása. Ugyanakkor mások is szükségét érezték egy szabad, nyílt forráskódú, hordozható és mégis egyszerű és használható teljesen objektum-orientált környezetnek. Így körvonalazódott a szándék, egy új Smalltalk implementáció megvalósítására, a felsorolt célok figyelembevételével.
A tervezés vázlatos folyamata:
Új image írása:
Új Smalltalkban írt virtuális gép:
|
A virtuális gép fordítása:
|
A kiegészítések megvalósítása:
1996 decemberében a Squeak-et az internethasználók nyilvánossága elé tárták. "Úgy éreztük végre azt tesszük ami 1980-ban nem sikerült." Három hétre rá megjelent az első adaptáció egy Unix-ra. Két héttel később hét további Unixra is átírták, és ezzel egyidőben megjelent az első Win95/NT változat. Öt hét leforgása alatt a Win3.1 kivételével minden főbb platformra megjelent egy Squeak változat. A folyamatos fejlesztések eredményeképpen a Squeak virtuális gép teljesítménye 1997 januárjára megtízszereződött a kezdeti állapotokhoz képest.
A Squeak végfelhasználói szerződés lehetővé teszi kereskedelmi programok írását is ebben a környezetben, teljesen ingyenesen. Az egyetlen megkötés ami a Squeak felhasználókat érinti hogy minden Squeak adaptációt vagy az alap osztálystruktúrát érintő változtatásokat közzé kell tenni az interneten, hogy mindenki számára elérhető legyen, valamint hogy minden kereskedelmi célra írt programot hasonló végfelhasználói szerződéssel kell ellátni.
Kívülről egy klasszikus 4 fájlos Smalltalk-nak néz ki, azaz van:
Sok alrendszer áll rendelkezésünkre, de nagyobbik részük opcionális, azaz nem szükségesek a rendszer működéséhez, ha nincs szükségünk rájuk eltávolíthatjuk őket. Ezáltal a normál Squeak 600 Kbyte környékére zsugorítható, de szükség esetén egy 250 Kbyte-os mini Squeak-et is használhatunk. Összehasonlításképp egy VisualWorks 2 Mbyte, a Java-t pedig ne is említsük. A Squeak csupán 1 Mbyte memoriával rendelkező rendszereken is elfut.
Az általam kipróbált és használt Squeak 3.2 build #4956 Windows-os változata 9.6 mega volt Zip-pel tömörítve, majd kibontás után mintegy 31 Mbyte helyet foglalt a merevlemezen. Természetesen ez a változat már az eredeti elképzelésekhez képest sokkal több kiegészítést tartalmaz (Flash player, stb.).
A Squeak teljes egészében és változtatások nélkül a Smalltalk-80 nyelvre épül. Ez az a nyelv amit a Squeak-en mint felületen belül használhatunk, és maga a fejlesztői környezet is ebben íródott, bár ahogy feljebb már szó volt róla, a hatékonyság érdekében a Smalltalk forrást először C-re fordították, majd ezt fordítottak tovább. Eltérések csupán a felületben, az alapkönyvtárrendszerben, és a multimédia kiegészítésekben vannak.
A Squeak esetében tehát nem beszélhetünk önálló nyelvről, mert az maga a Smalltalk-80, hanem egy erre épülő grafikus felületről és beépített könyvtárrendszerről egy virtuális gépről eshet szó. Éppen ez az oka annak, hogy ezen leírás nem a Programozási Nyelvek IV. tárgy szempontjai alapján készült.
Amikor elindítjuk a Squeak-et, akkor egy szöveges ablakkal, és néhány színes, szöveggel ellátott csíkkal találjuk szemben magunkat. Ezek a csíkok fejlécek, projekteket tartalmazó bezárt ablakok fejlécei. Egy projektet könnyen átnevezhetünk úgy, hogy az ablakának a fejlécszövegére klikkelünk. A projekt a fejléc bal végén lévő ikonnal törölhető, míg a jobb szélsővel megnyitható. Íme a kezdőkép:
Majdnem minden funkciót popup menükből érhetünk el! Így ha egy projektbe beléptünk, akkor abból kilépni, a bal egérgomb megnyomása után feljövő menü PREVIOUS PROJECT pontjának kiválasztásával tudunk. Minden jóváhagyott módosítást egy helyen, egy .image kiterjesztésű fájlban tárol a rendszer. De ténylegesen csak akkor írja a lemezre ki a módosításokat, ha a balgomb-menüben a SAVE menüpontra klikkelünk. Itt választhatjuk a SAVE AS, SAVE AND QUIT, QUIT funkciókat. Itt a Smalltalk teljes állapotát menthetjük, illetve kiléphetünk a rendszerből. A projektekhez tartozó helyi menü:
Ha véletlenül megsérülne az image fájl, nem kell megijednünk, egy .changes fájlban minden módosítást tárol a Smalltalk, így szinte bármely állapotát vissza tudjuk állítani a rendszernek. Persze ez a fájlt kissé meghízhat idővel, de ilyen problémák kezelése haladó Squeak-előkre tartozik... Az interneten keresgélve, olvashatunk az image fájl optimalizálásáról (méretének csökkentéséről), és később a menükben kutatgatva, hamar megtalálhatjuk a .changes fájlból való visszaállítás módját!
Első lépésként nyissunk magunknak egy project-et. Nyomjuk a főablak hátterén le az egér bal gombját, majd válasszuk ki az OPEN menüpontot, és utána a következő projekteket nyithatjuk meg:
Projektfajták:
Válasszuk a MORPHIC PROJECT-et. Nyissunk valami ablakot, amibe gépelhetünk a balmenü/open/TRANSSCRIPT, vagy balmenü/open/WORKSPACE menüpontokkal.
- MVC PROJECT
- standard project, itt a legnehézkesebb a felület kezelése.
- MORPHIC PROJECT
- itt már kényelmesebben ablakozhatunk, grafikázhatunk, az egyes grafikus elemeket akár rányithatjuk a projekt felületére.
- CONSTRUCTION PROJECT
- ez egyfajta vizuális szerkesztő, amelyet részletesen nem tárgyalunk.
Íme:
Az első azért előnyösebb, mert létezik egy transcript osztály, melynek osztályszintű SHOW metódusával bárhonnan üzenetet küldhetünk ebbe az ablakba. Nagyon hasznos lehet első próbálkozásaink során. Nyissuk meg mindkét ablakot, és a WORKSPACE-be írjuk be:
Miután entert ütünk az előző sorra, azt tapasztaljuk hogy nem történik semmi. Ez alapvető jellemzője minden Smalltalk rendszernek, hogy ki kell jelölni a bevitt kódrészletet, majd utasítani a rendszert hogy futtassa a kódot. Ezt a Squeak-ben vagy a jobbmenü/DO IT pontjának kiválasztásával, vagy az ALT+D billentyűkombináció segítségével tehetjük. Itt a menüben találhatunk egyéb hasznos funkciókat, melyek mindegyikéhez tartozik billentyűkombináció. A leghasznosabbak:
Fontos tudnivaló még, hogy majdnem minden objektumban megtalálható az INSPECT üzenet, amit ha meghívunk kkor egy DEBUG ablak jelenik meg a képernyőn, melynek segítségével nyomon követhetjük az objektum változóinak a változásait, kiolvashatjuk az értékeiket.
Aktiváljuk a balmenü/open/BROWSER menüpontot. Ekkor megjelenik a képernyőn egy úgynevezett SYSTEM BROWSER. Négy oszlopot láthatunk, melyek pontosan megfelelnek a Smalltalk szabványnak:
Minden oszlopban ha a SHIFT nyomva tartása mellett leütünk egy betűt, akkor ráugrik az első olyan lemre, aminek a neve ezzel a betűvel kezdődik. Az alsó szövegszerkesztő részben láthatjuk az adott elem forrását. Ha itt módosítunk valamin, ahhoz hogy a módosítás tényleg bekerüljön a rendszerbe, ALT-S-et kell nyomni. De ne feledjük ez csak a memóriában végzi el a módosításokat, ha azt akarjuk, hogy a lemezre is kiíródjon, akkor el kell menteni az egész Squeak állapotát! Fontos funkció még itt a System Browser-ben az osztály keresés (jobbmenü/Find Class).
Érdemes barangolnunk a System Browser segítségével az objektumok között, mert így megismerhetjük hogy milyen osztályok léteznek, és ezek milyen lehetőségekkel rendelkeznek. Például következőket emelném ki:
Morph-osztályok. Korábban az MVC-osztályok segítségével lehetett grafikát kezelni a Squeak-ben, de a MORPHIC osztályok sokkal kényelmesebb lehetőségeket nyújtanak. Minden alapvető építőelemet MORPH-nak hívunk. Minden ilyen osztály be van sorolva egy MORPHIC- szócskával kezdődő kategóriába. Egy MORPH komponenst a new üzenettel hozhatunk létre, ilyenkor mindig meghívódik az objektum initialize üzenete, ha öröklődünk MORPH-okból, akkor ebbe az üzenetbe írhatunk inicializálásokat.
Összetett grafikus objektumokat az AlignmentMorph
használatával hozhatunk létre. Ez az osztály talán a java Container-éhez
áll legközelebb. Ezeket egymásba ágyazhatjuk, vízszintesen, illetve
függőlegesen oszthatják meg az általuk kitöltött területet a hozzájuk
adott MORPH-ok közt. Az addMorph, illetve addMorphBack
üzenetek segítségével adhatunk egy MORPH-ot hozzá egy
AlignmentMorph-hoz.
Minden MORPH megnyitható a projekt
felületén is, az openInWorld üzenet meghívásával. Próbáljuk ki a
következőket:
A MORPH-ok kezelése eltér minden eddig megismert, és megszokott ablakozó rendszer kezelésétől. Ha lenyomjuk az ALT billentyűt, és így bal gombbal rákattintunk a MORPH-ra, valahol ott ahol nincs rajta input fókusz, akkor furcsa színes karikák jelennek meg körülötte. Ezekre klikkelve, vagy ezeket megragadva hajthatunk végre módosításokat a MORPH-on. Ha az egérmutatót egy ilyen karika fölé visszük, és ott várunk, akkor megjelenik a karika neve, ami jól meghatározza, hogy ennek segítségével mit tehetünk a MORPH-al. Például X-es karikával zárhatjuk be, a sárga karikával átméretezzük, a kékkel elforgathatjuk.
A System Browser-rel kalandozva megtudhatjuk, hogy milyen MORPHOK léteznek, és milyen attribútumaik, üzeneteik vannak. De megismerkedni a pontos használatukkal példákon, és Smalltalk programok átnézésén keresztül a legegyszerűbb.
A 2.7-es verzióhoz viszonyított különbségek, az eltelt idő fejlesztései rögtön szembetűnnek. Az alapkoncepció természetesen nem változott, azonban a felület egészen másképp néz ki:
A Squeak 3.2-es verziója öt darab előbukkanó eszköztárral van felvértezve (ezek: squeak, navigator, widgets, supplies, tools), és a legújabb divatnak megfelelően ezek már áttetszőek is lehetnek. Még mindig mindent elérhetünk helyi (popup) menükbol de az eszköztárak nagyban elosegítik a különböző opciók elérhetőségét. Mindezek mellett a rendszer beépített elemeire mozgatva a kurzort egy-egy buborék jelenik meg hasznos információkkal (amolyan windowsos módon). Szintén feltűnő változás hogy a főablak hátterén egy hatalmas Squeak logó folyamatosan szemmel követi a képernyőn mozgó kurzort. Az ablakok, eszköztárak animált mozgásúak. Mindemellett hozzá kell tenni, hogy az egész felületet lassúnak érzi az ember.
Alapállapotban négy ablakot látunk:
A hangkezelést, és az ehhez tartozó eszközöket hivatott bemutatni ez az ablak. A szöveges leírás mellett láthatunk egy hangszerszerkesztőt, melynek alján egy hatoktávos billentyűzet is helyet kapott. Természetesen ha ráklikkelünk valamelyik hangra akkor a kiválasztott vagy épp most szerkesztett hangszer megszólal. Emellett találhatunk egy lejátszó ablakot és egy dallamszerkesztő ablakot. Bár a dallamszerkesztő nem hangjegyekkel dolgozik, hanem különféle hosszúságú, színű és elhelyezkedésű csíkokkal, mégsem véletlen hogy az egész egy MIDI szerkesztőre hasonlít leginkább, hiszen a Squeak teljes MIDI támogatást nyújt. Be is tölthetünk és lejátszhatunk/szerkeszthetünk MIDI számokat.
Ebben az ablakban a Squeak beépített játékait próbálhatjuk ki. Három játék nyitva van és további hármat nyithatunk meg a szöveges állományból. Szintén jellemző rájuk a lassúság. Van tetris, passziánsz, miegymás...
Ez már érdekesebb és tartalmasabb ablak. Láthatunk többek között egy ferde "Squeak Rulez" feliratot valamint egy színválasztó ablakot. Amelyik színt kiválasztjuk a felirat abban pompázik. Látható egy nagyító buborék, amely mindig a kurzor környezetét nagyítja fel nekünk, valamint egy grafikus óra, és a Music résznél is említett zongorabillentyűzet, amely most is működik. Persze mindent és mindent szabadon áthelyezhetünk az ablakon belül. További érdekesség egy amorf alakzat és egy téglalap, melyeket egy kígyózó elhajlított vastag csík köt össze. Ebbe a három formába szöveg van beleírva. Az alakzatokat szabadon méretezhetjük És formázhatjuk, és a benne lévő szöveg mindig az aktuális viszonyokhoz igazodik. Eközben persze a három alakzatot szabadon és külön-külön mozgathatjuk.
Egy érdekes lehetoség. Könnyedén gyárthatunk rajzolt objektumokhoz scripteket. A bemutatott példában egy ablakba felrajzolt pályán, egy rajzolt versenyautót irányíthatunk egy mellérajzolt kormány forgatásával. Az autóhoz tartozik egy script ami adott állítható sebességgel mozgatja az autót a képernyőn, mindig a kormányról leolvasott irányba. Némi leírás segítségével ezt az egyszerű 'játékot' fejleszthetjük itt tovább újabb scriptek írásával.
Az internettel és a hálózati tevékenységekkel kapcsolatos információkat találhatjuk itt, mindössze egyetlen szöveges ablakban. Miután a Squeak tartalmaz beépített HTTP és FTP protokollokat és saját böngészőt (Scamper néven), így a szövegben egy linkre kattintva rögtön meg is nyithatjuk azt. Mindemellett a Squeak v3.2 része egy Celeste nevű e-mail kliens, egy Telenet nevű telnet kliens, egy IRC beszélgető-modul, egy PWS (Pluggable WebServer) és egy nagyobb teljesítményű Comanche webszerver.
Ezen ablakban pedig a Squeak 3D-t támogató eszközét ismerhetjük meg a Squeak-Alice-t. Ez egy Alice nevű 3D-s program Squeak-es implementációja. A háromdimenziós szerkesztéshez egyáltalán nem értő emberek is készíthetnek benne 3D-s virtuális világokat. Jelen esetben egy rózsaszín doboló nyuszit láthatunk egy zöld mezőn. A testrészeit külön kezelhetjük, mozgathatjuk a kamerát, állíthatjuk a fényhatásokat, és sok minden mást, természetesen a lehető legegyszerűbb módon, csupán néhány kattintással.
Az oldal az ELTE TTK Programtervező matematikus szakán tartott Programozási
Nyelvek IV. elnevezésű tárgy keretein belül készült, Bognár László 1999/2000
II. félévében készített munkája (Squeak 2.7 leírása) és a következő oldalak
felhasználásával, kiemelve a Squeak hivatalos honlapját, illetve a környezet
fejlesztői által írt elektronikus könyvet:
Kiemelve:
Továbbá:
Smalltalk leírás (hun)A Squeak implementáció által nyújtott Grafikus Interface Framework, Smalltalkban már létező régi Model-View-Controller alapú modelt váltja fel. Az új User Interface (UI) készítő rendszerünk alapvető osztálya a Morph. Gyakorlatilag az összes a képernyőn (World) megjelenő grafikus objektum valamely leszármazottjának a példánya. Squeak szerkesztőjében – ha nincs a funkció felüldefiniálva – jobb egérkattintással körvonalazódik egy-egy Morph object amivel szerkeszthetjük azt. Ezt a menüsort a grafikus objektum körül Halo-nak nevezzük. Így már látszik az előző állításunk is:
Ebből már ki is derül, hogy a keretrendszer fa szerkezetű megjelenítési hierarchiát használ. Minden Morphnak lehetnek hozzá relatív, azaz hozzátartozó Morph-jai, ezeket hívjuk SubMorph-nak. Ahogy azt az osztály definíciója mutatja:
Ezen kívül fel van tüntetve az Owner, amely a hierarchiában felette álló Morph-ot jelöli. Valamint van kiterjedése és színe is.
A UI processz értesíti a SmallTalk Morphic világát (World):
A Hand osztály valósítja meg az egér és a hozzá hasonló jellegű eszközöket pl.: RemoteMouse
Három alapvető osztályt kell ismernünk.
Minden grafikus osztály őse. Az ismerete azért fontos mert ellentétben más nyelvek grafikus keretrendszereivel (Java Swing) ez az ős nem absztrakt osztály. Önmagában is értelmezett, példányosítható. Amennyiben testreszabott grafikus osztályt akarunk létrehozni, belőle kell származtatni azt
Miden Morph-nak tartoznia kell valamilyen World –höz, direkt vagy indirekt módon. Ez alól az egyetlen kivétel a Drag&Drop során létezhet amikor is egy Hand-hez van rendelve az objektum.
Ez az osztály reprezentálja az egér kurzort.
A keretrendszer több kurzort támogat, még a távolról más rendszerekből irányított kurzort (remote hand), vagy előre rögzített eventek alapján működő HandMorphForReplay objektumot. Ez utóbbi remekül felhasználható olyan automatizált tesztek írására amelyek a Grafikus Interface-t tesztelik. Nagy előny ez más nyelvekhez képest, ahol ezekre külön keretrendszereket (Java-Sikuli, Selenium) kell, hogy írjanak és némelyikük így sem működi tökéletesen. Normális esetben egy elsődleges kurzor létezik egy World-ben (Az ActiveHand osztály referál rá), és egyetlen egy aktív kurzor lehet az event feldolgozása során.
Minden hand event forrás is, regisztrálhatunk, hogy ezekre az eseménykre, mint például mousedown, –move, -up. Alapvető esetekben a kurzor interakcióba lép a Morph példányokkal és így nem kell regisztrálnunk az eseményre. Minden kurzor tisztában van a billentyűzet állapotával. (A módosítók miatt szükséges)
Egy Hand objektum minden eseményét el tudja küldeni socket kapcsolaton keresztül, valamilyen távoli kurzornak.
Végül ezen osztály segítségével valósították meg a drag&drop funkcionalitást, valamint a help tooltippek „irányítását”.
Egy téglalap alakú Morph, amelybe más Morph példányokat illeszthetünk. Ezek együtt mozognak a PasteUpMorph példányukkal. Például a BookMorph lapjai ilyen típusúak. Egymásba is ágyazhatjuk őket.
Ezzel a három típusú Morph-al már használható alkalmazásokat készíthetünk, azonban léteznek még olyan esetek amik gyakran ezekétől eltérő funkcionalitást követelhetnek meg.
Gyakran előforduló probléma, ha egy ablak tartalmának mérete meghalajda az ablak méretét ennek a problémának a megoldására szolgál ez a típus (példa és a megvalósított objektum képen):
Ez egy „régi” osztály amely a subMorph-ok elrendezéséért volt felelős. Jelenleg ezt az elrendezést már a Morph Layout funkciói végzik
Eseménykezelést egy Morph-on három féle képpen végezhetünk:
Ez utóbbi kifejtve. Egy megfelelő Morph-ra így nézne ki:
Minden eventnek van egy neve/azonosítója (#mouseDown). Ezen esemény hatására elküldjük a recipientnek (jelen esetben self) a selectort (#clicked). A következő nevű eseményekre figyelhetünk ilyen módon:
Az előző példán bemutatott eseményre való regisztrálást visszavonhatjuk! De figyelnünk kell mert csak a következő módon tehetjük ezt meg:
Így egyetlen #click üzenetet sem fog elküldeni.
A Morph osztály objektumai önmagukban rengeteg funkcionalitást hordoznak, így az egyéni igényeket is gyorsan ki lehet velük elégíteni. Pár sor kód segítségével testreszabhajuk viselkedésüket, kinézetüket. Létrehozhatunk olyan ablakokat, amelyek nem téglalap alakúak, elforgatottak vagy teljesen máshogy viselkednek, mint az eddigi (más nyelvekben megismeret) User Interface-k. Ezen módosításokra adnék most pár példát:
Definiáljuk az osztályunkat a következő képpen:
Ezzel a származtatással máris egy használható, kirajzolható grafikus objektumot kapunk. Egy kék téglalapként jelenik meg a „Világban”. Amennyiben a megjelenését szeretnénk megváltoztatni példányainknak egyszerűen csak felül kell definiálnunk a Morph#drawOn: aCanvas metódustát. A Morphic rendszerben minden megjelenítést, rajzolást egy Canvas típusú objektumnak küldött üzetekkel végzünk. A canvas a rendszerünk rajzolási motorja. Sőt akár azt is megtehetjünk hogy a Morphic-ban megszokott FromCanvas helyett egy általunk származtatott Canvas-t használunk, így például létrehozhatunk egy RemoteCanvas-t, ami majd socket kommunikáción keresztül egy távoli asztalra rajzolja ki objektumainkat. Ha például az adott rendszeren a sznek nem engedélyezett a Canvas szürke árnyalatokat mappel hozzájuk és ezzel helyettesíti őket. Ha a drawOn: metódust implementáljuk mindezen renderelési opciók már adottak a kezünkbe.
Sok rendszer használ grafikus kontextust (egy objektumot) a renderelési opciók tárolására például a font vagy az előtér színére. Ez annyiban könnyíti meg a programozók dolgát, hogy nem kell minden egyes jellemzőt paraméterként átadni minden rajzolási függvényben. Azonban van egy hátulütője is. Más más futási utakon más állapotban marad a kontextus, ami hibát sorozatához is vezethet. A Morphic-ban explicit módon paraméterként adódnak át ezek a jellemzők , aminek előnye a hibák felderítésének és javításának könnyítése.
Legegyszerűbben úgy ismerkedhetünk meg a rajzolás lehetőségeivel, hogy megnézzük milyen selectorokat biztosít számunkra a FormCanvas osztály. Itt megtalálhatóak a szokásos függvények amelyekkel például téglalapot, vonalat, ellipszist tudunk rajzolni. Ezen metódusok segítségével testreszabhatjuk az elöbb létrehozott TestMorph osztályunk megjelenését, például egy ellipszis formájában. Használjuk az alábbi kódot ehhez:
A color objektum wheel metódusa egy tömböt ad vissza, amely a következő képpen működik. Ha N et adunk paraméterül akkor az N. szín a meglévő N-1 színtől legtávolabb eső -már ha a színeket egy körként ábrázol formában képzeljük el, és az ehhez geometriailag igazodó metrikát használjuk- szín lesz. Az első színünk az az objektum aminek a #wheel üzenetet küldtük.
Készíteni fogunk szintén a Morph osztály segítségével egy egyszerű rajzoló felületet mindössze hat metódus felüldefiniálásával körül-belül harminc sorban. Hozzuk létre az osztályt származtatással:
Deklaráltunk három példámny változót. A form változóban fogjuk tárolni a Form objektumot amire rajzolunk (ez azért kell mert átméretezésnél elveszne a Canvas), a brush változó lesz a toll (Pen), a lastMouse medig az előző egér kurzor helyet adja majd meg nekünk.
Biztosítsuk hogy az objektum kap egy alapértelmezett méretet. Ehhez felül kell definiálnunk az initialize metódust, aminek az implementációját a super initialize hívásával kezdjünk, amint már megszokhattunk SmallTalkban.
Most már a rajzolást megírni triviális lesz, mivel csak a bufferünkben lévő (form) canvas-t kell rárajzolnunk a Morph canvas-ára.
Ha ebben a pillanatban megnyitjuk az osztályunk egy példányát egy szürke téglalap alapú objektumot kapunk, amit át is méretezhetünk. Most már csak az esemény vezérlést kell megvalósítanunk. Két metódust kell még implementálni, amelyek az egér eseménykre figyelnek, illetve mégegyet, ami engedélyezi ezen események figyelését.
A mouseDown létrehoz egy Pen objektumot, amivel aztán a Canvas-ra tudunk rajzolni mindig az aktuális és az előző pontot összekötve. Ha ezt a felületet belerakjuk egy SystemWindow –ba már kész is van a kezdetleges rajzoló programunk. Nem is beszélve arról, hogy a Squeak futási időben is interaktív módon tudja a már emlitett Halo handle pontjaival kezelni a Morph-okat.
A következő kódot használjuk:
Ennek eredménye:
Így már mindjrát jobban fest.
A feladat egy olyan egyszerű rajzolóprogram készítése volt, amely Morphic objektumokat képes kirajzolni a rajzoló felületünkre. Ez azt jelenti hogy a sok látott rajzoló programtól eltérően, használ egy grafikus modelt, így a rajzolt ábrák nem csak a megjelenítő canvas-on "tárolódnak", hanem a modelben is. Ez a model Moprh objektumok egy halmaza.
Mivel a grafikus modellünk olyan, hogy a grafikus objektumok önmagukat rajzolják ki. Valamint mindegyikük származik a Moprh ősosztályból, így egyetlen mozdulattal lehet saját mintákat kirajzoló Morph objektumokkal bővíteni a programot
A Tool nevű osztályunkból származik a MorphTool nevű osztály. Ennek feladata a canvasról jövő események kezelése, tehát maga a rajzolás. A Morph tool konstruktorában nem egy objektumot, hanem egy Morph osztályt vár. Amelyből aztán ő maga példányosít objektumokat. Így a programunk minden olyan Morph-ot, amelynek a rajzolása a befoglaló téglalapjától függ szépen tud rajzolni.
A ToolHandler osztály biztosít kezelőfelületet az editorhoz. Példányunk létrehozásánál meg kell adni hogy milyen Tool-ok hoz szeretnénk kezelést, és hogy azok mely editorhoz tartozzanak. a metódus automatikusan generálja a kezelőfelületet és köti be az esemény kezelést.
Új, egyéni megjelenésű Morph osztályt létrehozását a Testreszabott grafikus elemek definiálása témakörben tárgyaljuk
Az ANSI Smalltalk -ot 1998. május 19. -én hagyták jóvá. A dokumentum neve: "American National Standard for Information Systems - Programming Languages - Smalltalk". A J20 technikai bizottság 1993-ban jött létre, hogy kidolgozzanak egy standardot, mely védi a Smalltalk felhasználók érdekeit a kompatibilitás és hordozhatóság szempontjából. Céljaikat három pontban foglalták össze:
A standard nem tartalmaz minden osztálykönyvtárat, amit elvárnánk, hogy egy Smalltalk implementáció tartalmazzon, például nem specifikálja sem a grafikus környezet sem pedig az adatbázis keretrendszereket, gondoskodik azonban arról, hogy legyen lehetőség létrehozni ilyen osztályokat. Vagyis a standard igyekszik a legkevésbé korlátozni az implementációkat.
Egy Smalltalk implementáció akkor felel meg a strandardnak, ha minden, a standardban meghatározott tulajdonságot pontosan a standarnak megfelelően teljesít. Ugyanakkor, ha a standardban egy szolgáltatást az „undefined” megjegyzéssel illetnek, akkor az arra utal, hogy a standardot megvalósító implementáció a szolgáltatással élő program elfogadása esetén ennek mikéntjét dokumentálni kell. Az „implementation defined” és a „unspecified” megjegyzéssel ellátott szolgáltatások esetén a standard megvalósítása azt jelenti, hogy kötelező módon meg kell valósítani ezeket, az előbbi esetén dokumentálva, az utóbbi esetén viszont nem szükséges a dokumentáció, csak egy értelemszerű megvalósítás. „Unspecified” esetre a leggyakoribb példa a protokollok visszatérítési értéke.
Egy Smalltalk program akkor felel meg a standarnak, ha csak és kizárólag a standardban meghatározott szolgáltatásokkal él, akár ha azok “undefined” vagy “implementation defined” típusúak. (Természetesen, az ilyen szolgáltatások használata csökkentheti a hordozhatóságot.) Ugyanakkor, léteznek “erroneous” megjegyzéssel ellátott szolgáltatások, ezek használatát el kell kerülje a program.
Az ANSI Smalltalk-ot meghatározó dokumentum a Smalltalk programot úgy definiálja, mint egy dinamikus számítógépes eljárás leírása, a Smalltalk - mint nyelv, pedig egy jelölésrendszer, mellyel ilyen programokat definiálhatunk. A Smalltalk, mint nyelv, meghatározása két összetevőből áll: az első az absztrakt számítógépes modell, ez meghatározza a környezeti elemeket, melyek adottak a leendő program számára, a második pedig a konkrét jelölésrendszer. Ezek együttesen valóban meghatározzák a nyelvet, de különválasztásuk biztosítja, hogy az implementációs technikák minimálisan legyenek befolyásolva
Az ANSI Smalltalk és a Smalltalk-80 közötti legalapvetőbb különbség az, hogy az ANSI Smalltalk teljes mértékben deklaratív leírást ad a Smalltalk programról, implementációs függőségek, részrehajló elemek teljesen el lettek távolítva a nyelvből.
Az ANSI standardot összefoglaló dokumentumban a következő környezeti egységeket tárgyalják ezen a témakörön belül:
Változó (variable): olyan entitás, amely egyetlen referenciát tárol egy objektumhoz, ez a változó értéke.
Az üzenet (message): egy kéres egy bizonyos művelet kivitelezésére. Az objektum egy olyan entitás, amely képes egy jól definiált üzenet halmazt értelmezni. Ugyanakkor bizonyos állapotok tárolására is képes.
Az objektum úgy válaszol egy bizonyos üzenetre, hogy végrehajt egy metódust (method). A metódusok egy bizonyos metódus szelektorral vannak asszociálva. A viselkedés (behavior) az a metódushalmaz, melyet az objektum használ arra, hogy válaszoljon a neki küldött üzenetekre.
A metódusok egy sor kifejezésből (expressions) állnak. A program futása a kifejezések egymásutáni kiértékeléséből áll, egy vagy több metóduson belül. Három típusú kifejezést ismerünk. Az értékadást (assignments), az üzenetküldést (message sends) és a visszatérítést (returns).
Az értékadás megváltoztatja egy változó értékét.
Az üzenetküldés felfüggeszti az éppen aktív metódus futását, és a következő metódus első kifejezésével folytatja. Az üzenet küldés címzettje egy objektum, ennek a neve a fogadó (receiver). Az üzenet egy metódus szelektorból és az argumentumokból áll. Minden argumentum ugyancsak egy objektum referenciaértéke.
A visszatérítés befejezi a metódus kiértékelését és visszaadja a vezérlést. Soron következik tehát a metódust meghívó metódus következő kifejezésének kiértékelése, az üzenet küldő kifejezés rákövetkezője. A visszatérítés egy értéket ad vissza, ez lesz a metódus lefutását előidéző üzenetküldés értéke.
A Smalltalk program szövegében vannak még azonosítók, változó nevek (variable names) amelyeket referenciaként használhatunk egy bizonyos változóra. Az egyedüli művelet mely engedélyezett egy program számára a változók kapcsán, hogy új értéket adjon egy változónak, illetve lekérje jelenlegi értékét.
Az állapot, melyet egy objektum megjelenít, egy sor változó, melyek kezdetben általában üresek. Ezek a példányváltozók (instance variables), melyek normális esetben egy-egy változónévhez vannak rendelve. Ugyanakkor az objektum állapotához tartozhatnak olyan névtelen változók is, melyeket jelzőszámokkal tudunk elérni. Az objektum állapota implementációfüggően less tárolva. A példányváltozókon kívül beszélhetünk diszkrét változókról (discrete variables) és az objektumoktól függetlenül léteznek. Azok a változók, melyeknek hatásköre a teljes program a globális változók (global variable), de vannak még osztály változók (class variables), illetve időszakos változók (temporary variables).
A program futása közben létező objektumok között vannak statikusan és dinamikusan létrehozottak. A statikusan létrehozott objektum egy egyedi objektum, melyet a Smalltalk program szövege pontosan meghatározott.Ilyenek például a literálok és az osztály objektumok.
A dinamikusan létrehozott objektumok nem egyedien létrehozottak, tulajdonképpen a metódusok kiértékelésének mellékhatásaiként jönnek létre és nincsen nevük sem.
A Smalltalk nem adja meg kifejezetten az objektumok megsemmisítésének módját. A koncepció szerint, ha egy objektum létre lett hozva, akkor a program futás ideje alatt mindvégig létezni fog. A gyakorlatban sok objektumot a programnak csak egy rövid részében használnak, a többi részben pedig teljesen mellőzve van. A Smalltalk implementációk garbage collection technikákat alkalmaznak, hogy felismerjék és visszanyerjék azokat az erőforrásokat, melyek olyan objektumokhoz vannak csatolva, melyeket már nem használ a program.
A környezeti elemek ismertetését követően az ANSI Standard jelölésrendszert mutat be. A hagyomány szerint a Smalltalk -nak nem volt olyan jelölőrendszere meghatározva, amely a teljes programra vonatkozna. A standard nem kívánja a Smalltalk ezen hagyományát megbontani, ezért csak egy absztrakt szintaxist határoz meg a Smalltalk program számára. Ez tartalmaz minden elemet, ami egy programban szerepelhet, és annak a módját, ahogyan ezek logikusan összeköthetőek az őket tartalmazó elemekben.
A jelölésrendszer bemutatását három fejezetre osztja. A lexikai nyelvtan (lexical grammar) az érvényes önálló karaktersorokat specifikálja, igazából ezek a Smalltalk nyelv tokenjeit határozzák meg. Ezek a tokenek lesznek azok az atomok, melyekből felépül a program. A metódus nyelvtan (method grammar) konkrétan meghatározza a metódusok létrehozásának és inicializálásának módját. Az absztrakt program nyelvtan meghatározza a teljes Smalltalk program absztrakt szintaxisát.
A Smalltalk program meghatározása egy sor program-elem meghatározása. Magába foglalja a diszkrét változókat, statikailag létrehozott objektumokat, és az objektumok viselkedését. Ezen kívül meghatározza a definíciók sorrendjét is. Egy konkrét definíció implementációfüggő lesz.
<< Smalltalk program >> ::= << program element >>+ << initialization ordering >>
<< program element >> ::= << class definition >> |
<< global definition >> |
<< pool definition >> |
<< program initializer definition >>
A << Program elemen t>> minden, a program által használt elem definiálását tartalmazza. Az << initialization ordering >> meghatározza az egyes program elemek inicializálásának sorrendjét. Értelemszerűen a program futása az első program elem inicializálásával kezdődik, majd sorrendben folytatódik.
A folytatásban a ANSI standardot közlő dokumentum bemutatja minden programelemre az absztrakt szintaxist, illetve a metódus és a lexikai nyelvtant.
A standard osztálykönyvtár tulajdonképpen az osztályok külsőleg észlelhető viselkedését specifikálja, az implementációs kérdéseket nem taglalva. Azt sem határozza meg, hogy milyen hierarchiában kell elhelyezkedjenek egymáshoz képest, még a példányváltozókat sem jelöli ki. Az általánosítás jegyében protokollokra támaszkodva határozza meg az egyes osztályok viselkedését. A protokoll egy szemantikus interfész, kifejezések és üzenet-meghatározások csoportja. Felvezetésükhöz külön jelölésrendszert vezet be az ANSI standardot összesítő dokumentum. Ezek után bemutatja az alap protokollokat, mint például
Standardnak megfelelő implementáció jellemzői alfejezet