Példányosítás reflectionnel, de belső osztályt.

2011.03.10. 07:30 FeniX- (törölt)

Érdekes kísérlet volt, a klasszikus GreenHouseControl példát újra elővenni, és átírni, csinosítani.

Kíváncsi voltam, hogy menne reflexióval, ha osztály objektumokat és konstruktor objektumokat használok.

A buktató a dologban az volt, hogy példányosítani kívánt objektumom belső osztály, így egy láthatatlan referenciát tárolnia kell az őt tartó osztályról.
A kód írásánál erre kifejezetten nincs szükség, mivel a compiler elvégzi helyettünk a feladatot, de példányosításnál kell hivatkoznunk erre a referenciára.
Erre kicsit később azért rájöttem magam is.

Íme a kis kódrészlet:
...
class Event {
   public Event(long value) { i = value; }
   private long i;
   // ...a többit elhagytuk.
}
class WaterOn extends Event {
   public WaterOn(long value) { super(value); }
}

...
GreenHouseControls osztályon belül pedig...
...


try {
     HashMap<String, Event> entities = new HashMap<String, Event>();
     entities.put("WaterOn", WaterOn.class);
     // entities.put... stb.,stb. Event osztály további leszármazottait..
     String typeName = "WaterOn"; 
     // .....
     Class evnt = null;
      if ((evnt = entities.get(typeName)) != null) {
         Constructor<? extends Event> c = 
         evnt.getConstructor(
            new Class[] {GreenHouseControl.class, long.class}
         );
         // GreenHouseControl.class a belső 'láthatatlan' osztályreferencia,
         // mivel Event-nek egyetlen egy konstruktora van, ami így fest:
         // public Event(long value) { ... }

         return
         (Event) c.newInstance(GreenHouseControl.this, System.currentTimeMillis());
    }
}
catch (NoSuchMethodException nsme) { }
catch (IllegalArgumentException iae) { } 

...

Megjegyzem, hogy ilyet soha ne csináljunk, hogy a hiba elkapásának helyén nem iratjuk ki legalább a stackTrace-t!
 

A régi kód többszörös if-else elágazásokból állt, és mindegyik ág egy konkrét példányt hozott létre a megfelelő osztályból.

Szólj hozzá!

Címkék: reflection

Paraméterezett típusok

2011.03.09. 08:40 FeniX- (törölt)

Néhány szót ejtenék a paraméterezett típusokról, ugyanis nemrégiben olvastam róluk, és nekem totál nóvum volt a dolog, illetve nem, de azért mégis.
Megmondom a frankót lesz erről később egy iromány (mármint a generikusokról), de most csak az egyszerü paraméteres osztályokról szeretnék beszélni.
Szóval vegyünk például egy egyszerű osztályt, amit később szeretnénk több paraméterrel is használni. Igazából most nem tudtam nagyon életszerü példát felhozni, ezért csak ilyen lolka-bolka kódot írtam össze.

/**
 * Ez az osztály képviseli példánkban
 * a paraméteres osztályt, ahol <T>
 * fogja jelenteni az aktuális paramétert.
 * Hót egyszerü osztály, két függvénnyel,
 * és egy privát változóval, mely szintén
 * a paraméteres típus tagja.*/

class SimpleParam<T> {
/**
         * Alap konstruktor, ahol
* paraméterben megadunk egy T típusú 
* változót.
*/

public SimpleParam(T value) {
this.i = value; // Átadjuk az értéket.
}
/**
* Beállítjuk i értékét.
* @param value i új értéke.
*/

public void setI(T value) {
this.i = value;
}
/**
* Visszakapjuk i értékét.
* @return i.
*/

public T getI() { return i; }
// Az egyszem változónk.
private T i;
}
// Fő osztályunk, ahol kipróbáljuk a paraméteres osztályt.
public class Parameterized {
public static void main(String... argv) {
SimpleParam<String> sp1 = new SimpleParam<String>("Hello World!"); System.out.println(sp1.getI()); // Érték kiiratása sp1.setI("Goodbye world!"); // Érték megváltoztatása. System.out.println(sp1.getI()); // Érték kiiratása.

SimpleParam<Integer> sp2 = new SimpleParam<Integer>(5); System.out.println(sp2.getI()); // Érték kiiratása. sp2.setI(123);         // Érték megváltoztatása. System.out.println(sp2.getI()); // Érték kiiratása.
}
}

Hasonlóan a paraméterezett ArrayList-hez, ezt az osztályt is példányosíthatom bármilyen referencia típussal.

Mivel ebben az osztályban csak egy módosító és egy hozzáférő metódus van, így attól sem kell tartani, hogy bármelyik objektumállapotban hibás működést fogok kapni. Erre azért oda kell figyelni.

Ha bárhol utánaolvastok a régi 'legacy' kódokban használt nyers típusokat nem ajánlják sehol, így ezeket érdemes elkerülni. ( pl. ArrayList al = new ArrayList(); ) 
Külön tanulmányok foglalkoznak azzal, hogy hogyan lehet régi kódot vegyíteni új, paraméteres, vagy generikus kóddal.

Update 1.: Rosszul fogalmaztam az előbbiekben, ez a kód is generikus, csak ezt szokták paraméterezett-nek is hívni. Az ArrayList analógiájára.

Update 2.: Fordításkor az összes ilyen generikus típus információ törlésre kerül, és a program nyers típusokra fordul le a generikusok esetén. Tehát kedvenc ArrayList<String>ünkből lesz egy sima ArrayList.

Viszont a kód fordítási időben garantálja, hogy csak a megfelelő típus kerülhet a kódunkba. ;-)

Szólj hozzá!

Címkék: generic

Hát akkor kezdjük.

2011.03.09. 07:48 FeniX- (törölt)

:-)

Sziasztok...ööö, Kár Karcsi vagyok..és Juditt..ja nem.

Igazából egy kezdő programozó irományait láthatjátok majd itt, legfőképp Jávában és Php-ben, és arra gondoltam, hogy együtt, Veletek lehetne fejlődni valamerre, mivel ilyen önfejlesztő szakkört még a neten semerre sem láttam, s gondoltam jó lenne, ha lenne ilyen.

A fő motivációt Tajti Ákos Jáva és C blogja adta, s mivel új bejegyzés oda már jóideje nem született, gondoltam, akkor legyen valami távolról sem hasonló, csak kicsiben, itt. ;-)

Legyetek jók, majd találkozunk.

Egyenlőre ezt az alap kinézetet meghagyom itt, mivel még csak ismerkedem a blogolás rejtelmeivel.

Jó mulatást mindenkinek, ne erőlködjetek tudjátok, csak lazán.

Üdv! 

 

u.i.: jajj tényleg, a legfontosabbat elfelejtettem mondani.
Mint mindenki én is csak emberből vagyok, és hibázhatok. Arra kérlek titeket, ha hibát vesztek észre a kódban, szóljatok, nem venném a szívemre, ha valaki miattam tanulna meg rosszul bizonyos dolgokat. :-)

Szólj hozzá!

Címkék: intro

süti beállítások módosítása