java kezdő: mit ír ki ez a kód? :D

Lehet hogy nagyon kezdő hiba, de ezt ma sikerült elkövetnem:


public class Horse {

public Horse() {
new Horse().makeSound();
}

protected void makeSound() {System.out.println("Nyiha-ha");}

public static void main(String [] args) {
new Horse();
}

}

Hozzászólások

Ilyet szoktam látni (meg elkövetni) hogy:


MyPanel extends Panel {

public MyPanel() {
this.setHeight(110);
..
..
..
}

}

Mármint hogy az adott elem gyakorlatilag a konstruktorában építi magát fel. És ez azért is rossz - szerintem - mert ezután ezt az elemet nehéz felhasználni arra hogy egy másik elem kiterjessze (tehát ez legyen a szülő osztája). Remélem érthetően írtam le.

Gondolom az objektum változói függenek a konstruktor paramétereitől. Persze lehet csinálni azt is, hogy nincs a konstruktornak paramétere, és meghívja a példányosítás után az ember az objektum.setValtozo(ertek);-eket, de ha adott esetben ezek a változók egymástól is függenek, akkor már arra is figyelni kellene, hogy milyen sorrendben vannak meghívva a set metódusok, és így egyszerűbb akkor egy metódusban implementálni. Viszont így akár már a konstruktor is lehetne ez a metódus.

Kicsit buta példa, de hirtelen jobb nem jut az eszembe (előfordulhat hogy hibás itt-ott*, de szerintem érthető mire gondolok): http://pastebin.ca/1952172

*: pl. az ifek záró zárójele lemaradt. :)

--
Don't be an Ubuntard!

Jaja...

Az állapotváltoztatás mindig számtalan hiba melegágya. Erre legkönnyebben akkor lehet rádöbbenni, ha az ember kicsit elmélyed a funkcionális stílusú programozásban és megtapasztalja mennyi hibától/extra gondolkodástól kímélhet ez meg, és mennyivel szabadabban és veszélymentesebben kombinálhatók így a különböző programrészek.

Ez alapján a helyes elv - ami persze teljesítményszempontból meg nem mindig ideális - ha:

Mindig a lehető legkorlátozottabb/legkevesebb/és jól definiált publikus állapot módosító mechanizmust definiálunk/használunk. Illetve pontosabban: ezeket úgy megtervezni, hogy az encapsulation élmény maximális legyen - azaz az elképzelhető legritkább esetekben kelljen ismerni az objektumok tényleges és részletes belső felépítését.

A konstruktor modulárisabb leírása (pl. több metódusra bontása) ezzel persze nincs ellentmondásban: bonyolult vagy átláthatatlanná váló konstruktorok esetén előnyös lehet a dekompozíció, olvashatósági szempontokat figyelembe véve.

Sokszor a kívülről egyszerűnek és megbízhatónak tűnő, minden szituban jól működő osztályok belülről nézve egészen eldurvulhatnak (állapotváltoztatások helyes sorrendezésének biztosítása, konzisztencia biztosítása, thread safety, megbízhatóság megmaradása mindenféle várható származtatott osztályok esetén stb...)

szerk.: Egyébként nekem ezek miatt az állapotmódosításra utaló "coding convention" szabályok is szimpatikusak. Pl a metódus nevének végén ! használata (scheme, ruby) vagy az, hogy az állapotmódosító metódusokat mindig void visszatérési értékkel definiáljuk (Eiffelben szokás asszem)
Nem is beszélve a deklaráltan inmutable oszályokról ugye ;) (A legklasszikusabb minden nyelvben felmerülő példa ugye hogy mutable, vagy inmutable-e az alapértelmezett sztring típus, ami a "biztonság vagy a teljesítmény a fontosabb" kérdés mentén történő jellemző törésvonal...)

A konstruktor valoban lehetne, de mint lattuk, nem jo otlet. A singleton viszont pont azt csinalja, hogy a privat konstruktort kepes meghivni, adott esetben akar parameterezve is. A singletonnak az a lenyege (fixme) hogy az objektum konstruktoron keresztul nem peldanyosithato, arrol viszont nem mond semmit, hogy a peldanyosito metodusnak lehet-e parametere.


public class MySingleton {
  private int arg1;
  private String arg2;
  protected MySingleton(int arg1, String arg2) { 
    this.myArg1 = arg1; this.myArg2 = arg2; 
  }
  public static newInstance(int arg1, String arg2) { 
    return new MySingleton(arg1, arg2); 
  }
}

--


Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.

Háááát ööö., ez így nem oké. Nem hozhatsz létre new-val objektumot ha protected a konstruktor.
A sigleton (vagy általánosítva akárhány-ton) értelme, hogy globálisan korlátozod az adott osztályba tartozó létrejövő objektumok számát (általában egyre).

Azaz a kódodba kell egy:
private MySingleton ehh=null;

a konstruktor protected és még egy:

public static getInstance(...){
if(ehh==null) ehh= new Mysingleton(...);
/*ehh.set(...);*/ return ehh;
}

Azaz mindig tökéletesen ugyanazt a példányt kapod a MySingleton.getInstance(...); hívással. A ruby persze elrejti a mocskos részleteket az "include Singleton" mixinnel ugye? ;) De ott is ez van a hátterében...

Persze az tény, hogy singleton esetén nem lesz végtelen rekurziós konstruktorod, de azért nem ez fő célja/haszna... (Na jó, persze ha béna vagy, a protected konstruktorba is rakhatsz végtelen rekurziót, az ellen nem véd ;)

Varj, amig az osztaly kodjan belul vagyok, addig mindegy, addig siman rahivhatok a konstruktorra, mert a protected/privat a kulso elerest szabalyozza.

A getInstance() valoban igy mukodik, am a newInstance() pont azert lett igy elnevezve, hogy nem ugyanazt a peldanyt adja vissza.

En nem a vegtelen rekurzios konstruktorra akartam reagalni, hanem BaT -nak arra a felvetesere, hogy hogyan lehetne jol, gyorsan, es egyszeruen tobb dolgot megmondani egyszerre egy peldanynak. Erre a parameterezheto newInstance() tokeletesen alkalmas.
--


Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.

Igazad van ,részben elnéztem a kódod... De az tény, hogy singletonon nem ezt értik.

A konstuktorok elrejtése egy metódusnév alá ilyen módon, meg nem tudom mikor hasznos...

Egyszerre "több dolgot mondani" a konstruktoron belül is lehet (ugyanazokat megteheted benne mint egy bármely másik metódusban), ha pedig erre nem mindig van szükség írhatsz több konstruktort is (overloading), vagy adhatsz neki valamilyen "options" paraméter(eke)t.

Java eseten ha protected a konstruktor, akkor nem lehet sehogyan sem peldanyositani az osztalyt. Ez foleg akkor tud jo lenni, ha pl. kell meg valami ellenorzes a konstruktorhivas utan, amit el akarsz rejteni a felhasznalok elol.
--


Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.

stack overflow :)
amikor letrehozol egy uj objektumot meg nem leteznek a metodusai, amit meghivhatnal.

Nem pont a létezés a kérdés, hanem hogy:
1. fut egy konstruktor
2. amin belül fut egy konstruktor
3. amin belül fut egy konstruktor stb...

Szóval ilyen kód után nem fut semmi ha létezik, ha nem.

Valami ilyesmi történik röviden:
a() {
a(); print("Hello");
}

A végtelen rekurzió utáni utasításokra nem kerül sor.