Jsou Java generics opravdu špatné?

Jsou Java generics opravdu špatné?
« kdy: 10. 05. 2014, 22:10:36 »
Ak viete niekto sposob ako urobit toto tak, aby to nedavalo v Java error tak mi prosim povedzte.

Kód: [Vybrat]
class Foo {
    public Foo(String ohMyName) {
        // bla bla
    }
}

class SuperGeneric<F extends Foo> {
   
    void notWorkingMethod() {
        F f = new F("Chuck Norris");
    }   
   
}

Ja viem, ze je mozne dostat objekt Class<F>, a potom volat cls.newInstance(), ale tam nie su podporovane parametre konstruktoru?
Skratka, ako vytvorit objekt generickeho typu, pomocou konstruktora s parametrom/parametrami?
Pre mna to zatial vyzera tak, ze je to nemozne, a ak je to tak, tak Java generics su naozaj hlupy vtip.
« Poslední změna: 11. 05. 2014, 21:17:05 od Petr Krčmář »


Re:Su Java generics naozaj az taketo zle?
« Odpověď #1 kdy: 10. 05. 2014, 23:11:09 »
Java generiky jsou dostupné pouze kompilátoru, bajtkód se při jejich zavedení nijak neměnil. Při běhu tedy JVM o F nic neví, takže nemůže zavolat jeho konstruktor. Navíc i když se na ten kód podíváte, je nesmyslný. F je libovolný potomek Foo (nebo Foo samotné) - na jaké třídě by se tedy konstruktor měl volat? Vybrat si náhodně Foo nebo nějakého jeho potomka?

Konstruktory třídy získáte přes Class.getConstructors(), případně přes Class.getConstructor(Class<?>... parameterTypes) získáte konkrétní konstruktor.

Doporučuju nejprve si nastudovat věci, které chcete používat - programovat metodou pokus-omyl se moc nedá.

perceptron

Re:Su Java generics naozaj az taketo zle?
« Odpověď #2 kdy: 11. 05. 2014, 10:10:47 »
vas priklad sa po "type erasure" (odstraneni generik v case kompilacie) premeni na:

Kód: [Vybrat]
class Foo {
    public Foo(String ohMyName) {
        // bla bla
    }
}

class SuperGeneric {
   
    void notWorkingMethod() {
        ????????? o = new ????????("Chuck Norris");
    }   
   
}
kompilator nevie, co s vasim konstruktorom: jednak nevie urcit datovy typ a jednak vase generikum je "hocico, co dedi od Foo", co vedie k tomu, ze chcete vytvorit "novu instanciu hocicoho, co dedi od Foo".

generika nie su az tak prefikane vymyslene ako v .net, lebo sa musela zachovat spatna kompatibilita, miestami su dost sialene, ale rozhodne by som to nenazyval hlupym vtipom. chcelo by to z vasej strany lepsi priklad, lebo taketo vseobecne priklady z brucha sa mnohokrat daju urobit uplne inak.

a samozrejme, skuste hodit oko do legendarneho faqu angeliky lokotz: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

Re:Su Java generics naozaj az taketo zle?
« Odpověď #3 kdy: 11. 05. 2014, 10:18:31 »
vas priklad sa po "type erasure" (odstraneni generik v case kompilacie) premeni na:

Kód: [Vybrat]
class Foo {
    public Foo(String ohMyName) {
        // bla bla
    }
}

class SuperGeneric {
   
    void notWorkingMethod() {
        ????????? o = new ????????("Chuck Norris");
    }   
   
}

To není úplně přesné, ve skutečnosti by se to přeložilo takto:

Kód: [Vybrat]
class Foo {
    public Foo(String ohMyName) {
        // bla bla
    }
}

class SuperGeneric {
   
    void notWorkingMethod() {
        Foo f = new ??????("Chuck Norris");
    }   
   
}

perceptron

Re:Su Java generics naozaj az taketo zle?
« Odpověď #4 kdy: 11. 05. 2014, 12:17:08 »
to je pravda, vdaka za korekciu a dovzdelanie


Re:Su Java generics naozaj az taketo zle?
« Odpověď #5 kdy: 11. 05. 2014, 13:13:54 »
Konstruktory třídy získáte přes Class.getConstructors(), případně přes Class.getConstructor(Class<?>... parameterTypes) získáte konkrétní konstruktor.

Dakujem za odpoved. Vidim teda, ze sa to da, to je skvele, nie su tie generika predsa az TAKE zle. Aj ked musim explicitne poskytovat Class objekt, co je dost neohrabane.

chcelo by to z vasej strany lepsi priklad, lebo taketo vseobecne priklady z brucha sa mnohokrat daju urobit uplne inak.

Ten priklad co som uviedol je iba zjednodusenou abstrakciou realneho problemu, ktory riesim. A naozaj v nom potrebujem vytvarat nove instancie danej generickej triedy pomocou konstruktora s parametrami.

greg

Re:Su Java generics naozaj az taketo zle?
« Odpověď #6 kdy: 11. 05. 2014, 14:37:19 »
Ten priklad co som uviedol je iba zjednodusenou abstrakciou realneho problemu, ktory riesim. A naozaj v nom potrebujem vytvarat nove instancie danej generickej triedy pomocou konstruktora s parametrami.

Obavam sa, ze tym, ako to chces spravit, porusujes OOP principy. SKus to spravit tak, aby konstruktor bol vzdy bez parametrov. Vsetko, co potrebujes odovzdat danej instancii odovzdavaj cez set* metody. Takto velmi pekne vyriesis aj rozne veci, ktore ti budu sakra vadit pri robeni testov.

OS: Ako zarucene nasrat slovensky pisuceho prispievatela? No predsa otazkou: "Ve kterém měsíci proběhla sametová revoluce?"

Re:Su Java generics naozaj az taketo zle?
« Odpověď #7 kdy: 11. 05. 2014, 14:47:02 »
Obavam sa, ze tym, ako to chces spravit, porusujes OOP principy. SKus to spravit tak, aby konstruktor bol vzdy bez parametrov. Vsetko, co potrebujes odovzdat danej instancii odovzdavaj cez set* metody. Takto velmi pekne vyriesis aj rozne veci, ktore ti budu sakra vadit pri robeni testov.
Já tenhle přístup naopak nemám rád. Pokud se nějaká hodnota nastavuje jenom při inicializaci objektu, dám field final a nastavuju ho v konstruktoru. Podle mne by měl být po provedení konstruktoru objekt plně inicializovaný a připravený k použití, ne že musím zjišťovat, co vše je ještě nutné nastavit.

Re:Su Java generics naozaj az taketo zle?
« Odpověď #8 kdy: 11. 05. 2014, 14:53:29 »
Obavam sa, ze tym, ako to chces spravit, porusujes OOP principy. SKus to spravit tak, aby konstruktor bol vzdy bez parametrov. Vsetko, co potrebujes odovzdat danej instancii odovzdavaj cez set* metody. Takto velmi pekne vyriesis aj rozne veci, ktore ti budu sakra vadit pri robeni testov.
Já tenhle přístup naopak nemám rád. Pokud se nějaká hodnota nastavuje jenom při inicializaci objektu, dám field final a nastavuju ho v konstruktoru. Podle mne by měl být po provedení konstruktoru objekt plně inicializovaný a připravený k použití, ne že musím zjišťovat, co vše je ještě nutné nastavit.

Uplne suhlasim. Ja aj namiesto:

public void setFoo(float value) {
    this.foo = value;
}

public float getFoo() {
    return foo;
}


Davam proste public float foo;
Ak to niekto povazuje za porusenie OOP principov, tak nech mi povie, v com sa public field lisi od hore uvedenych getterov a setterov.

Aj ked uvedomil som si, ze v mojom pripade mozem do danej triedy pridat aj default konstuktor, ktory proste nastavi defaultne hodnoty, pretoze tie su neskor zmenitelne.

Re:Su Java generics naozaj az taketo zle?
« Odpověď #9 kdy: 11. 05. 2014, 15:06:39 »
Ak to niekto povazuje za porusenie OOP principov, tak nech mi povie, v com sa public field lisi od hore uvedenych getterov a setterov.
Rozdíl je v tom, že při použití getterů a setterů můžete změnit implementaci, aniž byste změnil kontrakt. Např. můžete do setteru později přidat odpálení události propertyChange.

Kit

Re:Su Java generics naozaj az taketo zle?
« Odpověď #10 kdy: 11. 05. 2014, 15:31:06 »
Davam proste public float foo;
Ak to niekto povazuje za porusenie OOP principov, tak nech mi povie, v com sa public field lisi od hore uvedenych getterov a setterov.
Špatně je obojí. Vznikají tím anemické modely, které mají zbytečně košaté rozhraní a přitom nic neumí.
Aj ked uvedomil som si, ze v mojom pripade mozem do danej triedy pridat aj default konstuktor, ktory proste nastavi defaultne hodnoty, pretoze tie su neskor zmenitelne.
Defaultní hodnoty je zbytečné dávat do konstruktoru. Atributy je možné nastavit v deklaraci, je to také mnohem přehlednější.

perceptron

Re:Su Java generics naozaj az taketo zle?
« Odpověď #11 kdy: 11. 05. 2014, 15:33:41 »
dodanie parametra typu Class je bezna praktika (nazvite si to workaround ak chcete), v springu sa pouziva bezne

to, ci trieda musi mat vsetky zavislosti / veci potrebne pre beh uz v konstruktore, alebo dodatocne, je otazka konvencii a konkretneho, oba maju pre a proti. taky zmieneny spring pouziva settery a anotaciu (@postconstruct, initializingbean), ine frameworky pchaju vsetko do konstruktora. opticky mam pocit, ze java pouziva skor settery a gettery, ... lebo tradicia.

v kazdom pripade, public premenne su grc. pythonisti maju na to oznacenie "unpythonic", ak chcete

Citace
Ak to niekto povazuje za porusenie OOP principov

lebo ked nahodou potrebujete pri nastaveni premennej dodat dalsie operacie (napr. zalogovat), mate smolu
okrem toho milion frameworkov vie pracovat s gettrami a settrami (javabeans konvencie) a su nervozne, ked nenajdu gettery a settery
okrem toho, triedy su definovane metodami a nie stavom (kontrakt, ako povedal p. Jirsak). zial, java nema properties ako groovy, javascript ci c#, tak sa to riesi prave takto, ale principialne si na to velmi rychlo zvyknete (kazde ide vam ich vygeneruje)



Re:Su Java generics naozaj az taketo zle?
« Odpověď #12 kdy: 11. 05. 2014, 15:56:25 »
co takhle pridat factory:

Kód: [Vybrat]
public interface myFactory<F extends Foo>{
F newInstance(Object... args);
}
Misto "Object... args" dej svoje argumenty

a v ty metode si objekt vyzadat od factory. Jednou jsem v enumu reflexi predelal prave na factory, aby to bylo cistejsi a i lepe citelne, timto figlem se vtyvareji tovarni metody, ktere musi mit urcitou signaturu

Natix

Re:Su Java generics naozaj az taketo zle?
« Odpověď #13 kdy: 11. 05. 2014, 18:34:06 »
Public fieldy kromě toho, že neumožňují abstrakci přímo v dané třídě (tzn. nemůžu přidat logování, validaci, delegaci, nebo cokoliv jiného do setteru), tak navíc ani nejsou virtuální, takže je nemůžu ani overridovat v potomkovi. Public fieldy nebrat.

greg

Re:Su Java generics naozaj az taketo zle?
« Odpověď #14 kdy: 11. 05. 2014, 20:56:59 »
Dalsi problem nastavovania niecoho v konstruktory stylom, ze spravim novy objekt s ktorym mam pracovat je problem toho, ze si napriklad vysvorim vlastnu instanciu spominaneho F v konstruktore, ale pouzivatel chce znovupouzitelnost a chce moju triedu pouzit s triedou FmojeVlastneKrajsieAkoPouzilANahardkodilOn. Uz instanciu tejto triedy ale dany clovek s tvojim kodom nepouzije, lebo ty si vytvaras instanciu sam v konstruktore... Jedine oddedit tvoju triedu a overrajdnut tvoj konstruktor. Ale naco niekomu pridavat pracu, ked mozes spravit defolt konstruktor, kde si vytvor co chces, ale nasledne vytvor i konstruktor (alebo setter), kde si mozem ako pouzivatel tvojeho kodu dat cokolvek, co dedi od F (ked uz to generikum chces pouzit).