Bevezetés
Tanfolyamunk utolsó leckéjében azt mutatjuk be, hogy hogyan lehet NetREXX-ben JavaBeaneket (Java babszemeket?) készíteni. A JavaBeanek olyan különálló objektumok, amelyekbôl a Java fejlesztôkörnyezetek (pl. VisualAge for Java) építkeznek. A JavaBean tehát egyfajta építôelemnek is tekinthetô. Tanfolyamunk során csak az egyszerû beanekkel fogunk foglalkozni és nem fogunk belemerülni a JavaBeanek készítésének minden apró részletébe.
JavaBean alapok
Egy JavaBean nem más, mint egy Java osztály, amely rendelkezik a következô összetevôkkel:
| Tulajdonságok (Properties) | Az osztály állapotát leíró állapotváltozók, vagy más néven tulajdonságok. Háromféle fajtájuk létezik. Az egyszerû állapotváltozók értékének megváltozása nem jár semmilyen esemény bekövetkezésével. A kapcsolt (bound) változók értékének módosulása viszont mindig maga után vonja a PropertyChange esemény bekövetkezését. Amennyiben az állapotváltozó értékének megváltozásában érdekelt osztályok regisztrálják magukat a PropertyChangeListener listára történô feliratkozással, akkor minden esetben értesülnek a változásról. A harmadik típusú, feltételes állapotváltozók olyan változók, amelyeknek értékének módosulását más osztályok ellenôrzik és szükség esetén meg is akadályozhatják. |
| Metódusok | Publikus, vagyis más osztályok által meghívható metódusok. |
| Események (Events) | A beanen belül bekövetkezô események, amelyek más, az esemény bekövetkezésének értesítési listájára feliratkozott osztályokban folyamatokat indít el. A PropertyChange esemény például egy ilyen esemény, amely a kapcsolt és feltételes tulajdonságok megváltozásakor generálódik. |
A JavaBeanekhez a legtöbb esetben tartozik egy úgynevezett bean információs osztály is, amelyben definiálják az állapotváltozók, metódusok és események nevét. Mivel az állapotváltozók és metódusok nevét magából a beanbôl is ki lehet nyerni, ezért ezek definiálása opcionális. Az események nevének megadása ugyanakkor kötelezô.
Egy egyszerû JavaBean
Példaként alkossunk meg egy JavaBeant, amely egy alkalmazottat reprezentál. A bean három állapotváltozóból, két metódusból és egy eseménybôl fog állni. Az állapotváltozók az alkalmazott száma, neve és fizetése lesznek. A fizetést az increaseSalary és decreaseSalary metódusok segítségével lehet növelni és csökkenteni. Amennyiben a fizetés meghalad egy bizonyos értéket, akkor egy figyelmeztetô eseményt fog a bean generálni. Egy bean megírása minden esetben a JavaBeans package importálásával és a class utasítással kezdôdik:
import java.beans. class lecke11a public binary
A második lépés a privátként definiált állapotváltozók felsorolása:
properties private fieldNumber = int 0 fieldName = String null fieldSalary = float 0
Esetünkben mindegyik állapotváltozó rendelkezik egy get metódussal, amellyel lekérdezhetô az adott változó értéke:
method getNumber() public returns int return fieldNumber method getName() public returns String if fieldName == null then fieldName = String "" return fieldName method getSalary() public returns float return fieldSalary
A get metódusok mellett meg kell adnunk a set metódusokat is, amelyekkel az állapotváltozók értékét lehet megváltoztatni. Sajnos ezen metódusok megalkotása kicsit körülményesebb, mivel kapcsolt változókat használunk, és ezek értékének módosulásakor generálnunk kell egy PropertyChange eseményt is. Ehhez nem kevesebb mint három metódusra van szükség:
properties inheritable propertyChange = PropertyChangeSupport(this) method addPropertyChangeListener(listener=PropertyChangeListener) public protect propertyChange.addPropertyChangeListener(listener) method removePropertyChangeListener(listener=PropertyChangeListener) public protect propertyChange.removePropertyChangeListener(listener) method firePropertyChange(propertyName=String, oldValue=Object, newValue=Object) public propertyChange.firePropertyChange(propertyName, oldValue, newValue)
Mindazon osztályok, amelyek értesülni akarnak egy adott tulajdonság értékének megváltozásáról, fel kell hogy iratkozzanak az addPropertyChangeListener metódussal az értesítési listára és implementálniuk kell a PropertyChangeListener interfészt, vagyis rendelkezniük kell egy saját PropertyChange metódussal. A leiratkozás a removePropertyChangeListener metódussal történhet. A bean firePropertyChange metódusa meghívja az értesítési listára feliratkozott osztályok PropertyChange metódusát, hogy azok megkapják a változás hírét és elvégezhessék a számukra ilyenkor elôírt feladatokat.
Ezek után már nincs más hátra, mint hogy megalkossuk a három tulajdonság set metódusát:
method setNumber(number=int) public
oldValue = int fieldNumber
fieldNumber = number
firePropertyChange("number", Integer(oldValue), Integer(number))
method setName(name=String) public
oldValue = String fieldName
fieldName = name
firePropertyChange("name", oldValue, name)
method setSalary(salary=float) private
oldValue = float fieldSalary
fieldSalary = salary
firePropertyChange("salary", Float(oldValue), Float(salary))
Amint látjuk, mindhárom set metódus meghívja a firePropertyChange metódust, hogy figyelmeztesse az értesítési listára feliratkozott osztályokat a kapcsolt állapotváltozók értékének megváltozásáról. Figyeljük meg, hogy a változók régi és új értékét az Object osztály alosztályaként (Integer vagy Float) kell átadni! A setSalary metódust privátnak deklaráltuk, mivel azt akarjuk, hogy az alkalmazott fizetését csak az alábbiakban bemutatandó increaseSalary és decreaseSalary publikus metódusokkal lehessen csökkenteni illetve növelni:
method increaseSalary(amount=float) public setSalary( getSalary() + amount ) method decreaseSalary(amount=float) public setSalary( getSalary() - amount )
Ezekben a metódusokban már nem hívtuk meg a firePropertyChange metódust, mivel az megtörténik a setSalary privát metódus meghívásakor.
A metódusok után már csak a bean harmadik összetevôjét, az esemény(eke)t kell megalkotnunk. Az események a kapcsolt állapotváltozókat manipuláló metódusokhoz hasonlóan három összetevôbôl állnak. Minden esetben szükség van ugyanis két olyan metódusra, amelyekkel az értesítési listára lehet fel- illetve leiratkozni, valamint egy olyan metódusra, amelyik triggereli az eseményt:
properties inheritable aActionListener = Vector null -- értesítési lista method addActionListener(newListener=ActionListener) public -- feliratkozás if aActionListener == null then aActionListener = Vector() aActionListener.addElement(newListener) method removeActionListener(newListener=ActionListener) public -- leiratkozás if aActionListener \= null then aActionListener.removeElement(newListener) method fireActionPerformed(e=ActionEvent) if aActionListener == null then return currentListeners = aActionListener.clone().elements() loop while currentListeners.hasMoreElements() (ActionListener currentListeners.nextElement()).actionPerformed(e) end
Amint látjuk, az értesítési lista tulajdonképpen nem más, mint egy vektor, amelyben eltároljuk mindazon osztályok referenciáját, amelyek értesítést akarnak kapni az esemény bekövetkezésérôl. Amikor az esemény bekövetkezik, akkor meg kell hívnunk a fireActionPerformed metódust, amely elküldi az összes regisztrált osztálynak az esemény bekövetkezésének hírét. Példaprogramunk esetében egyetlen eseményt kell csak jeleznünk. Azt szeretnénk ugyanis, hogy ha a fizetés átlép egy bizonyos határértéket, akkor figyelmeztessük az ebben érdekelt osztályok:
properties constant
salaryLimit = float 100 -- 100 egység a limit
method setSalary(salary=float) private
oldValue = float fieldSalary
fieldSalary = salary
if salary > salaryLimit then do
salary = salaryLimit
fieldSalary = salaryLimit
fireActionPerformed( ActionEvent( this, -
ActionEvent.ACTION_FIRST, -
"SALARY-LIMIT" ) )
end
firePropertyChange("salary", Float(oldValue), Float(salary))
Ahhoz, hogy meghívhassuk az esemény bekövetkezését jelzô metódust, létre kell hoznunk egy ActionEvent objektumot, amelyik tartalmazza az esemény forrását, az esemény kódját és egy, az eseményt leíró karakterláncot.
Beanleíró osztályok
Mivel példánk egy eseményt is tartalmaz, ezért mindenképpen készítenünk kell a beanhez egy leíró osztályt is. Amennyiben a bean csak tulajdonságokból és metódusokból állna, abban az esetben ez nem lenne kötelezô, mivel a többi osztály meg képes határozni a bean publikus interfészét (lásd Java introspection support a JDK dokumentációban). Példánk esetében a leíró osztály a következôképpen nézhet ki:
import java.beans.
class lecke11b extends SimpleBeanInfo public binary
properties private
beanClass = Class
method lecke11b() public -- konstruktor
beanClass = Class.forName("lecke11b")
method getEventSetDescriptors() returns EventSetDescriptor[ ] public -- az esemény definíciója
eventDesc = EventSetDescriptor[1]
do
eventDesc[0] = EventSetDescriptor( beanClass, "actionPerformed", -
ActionListener.class, "actionPerformed" )
eventDesc[0].setDisplayName("empEvent" )
eventDesc[0].setShortDescription("employee event" )
return eventDesc
catch Throwable
end
return null
Az állapotváltozók és metódusok leírására az xxxxxPropertyDescriptor és xxxxxMethodDescriptor metódusokat lehet használni, ahol xxxxx helyébe az állapotváltozó vagy a metódus nevét kell behelyettesíteni.
A beanek használata
Amennyiben elkészültünk a NetREXX-ben megírt beannel, akkor elôször át kell fordítani a kódot Java nyelvre, hogy a bean használható legyen például VisualAge for Java-ban. A Java kódra történô fordítást a NetREXX fordító -keep opciójával lehet elvégezni:
nrc lecke11a -keep nrc lecke11b -keep
Az eredményül kapott lecke11a.java.keep és lecke11b.java.keep fájlokat nevezzük át *.java-ra! Importáljuk az így kapott Java fájlokat a VisualAge for Java-ba, majd nyissuk meg a lecke11a osztályt és lapozzunk a BeanInfo oldalra. Válasszuk ki mindegyik tulajdonságot és állítsuk a bound attribútumot TRUE-ra! Az eljárás hatására újra fog generálódni a teljes lecke11b osztály. A bean ezek után szabadon felhasználható appletekben vagy alkalmazásokban.
REXX GYÍK:
K1. Miért érdemes NetREXX-ben Java beaneket írni?
V1. Ennek több oka is lehet. NetREXX-ben könnyebben és gyakran tömörebben lehet programozni, mint Java-ban. Esetenként a már klasszikus REXX-ben megírt programrészletek újrafelhasználásának könnyedsége is jó érv lehet a NetREXX mellett.
Gyakorlat:
1. Alakítsa át a példa beant oly módon, hogy az a fizetés egy alsó határértékének átlépésére is eseményt generáljon!
2. Bôvítse ki a példabeant további állapotváltozókkal (pl. alkalmazott neme, lakcíme, beosztása, stb.). Hozza létre az új állapotváltozók értékének manipulálásához szükséges metódusokat is!
3. Készítsen appletet a VisualAge for Java-ban a példabean felhasználásával!
| Kádár Zsolt 2000. 08. 24. | [ Elôzô lecke | Tartalom ] |