12 komentáře “This (self) v generikách

  1. Bude to asi hloupy dotaz, ale proc je class AbstractParent deklarovana abstraktni? Ma to nejaky vyznam v tom prikladu, nebo nad tim premyslim zbytecne?

    • IMHO – Abstract je možné klidně vynechat a generiky to neovlivní. V příkladu je to hlavně proto, aby čtenář očekával, že funkce této třídy je pouze v tom, že má sloužit jako předek pro nějaké potomky, který sám o sobě nemá valný význam.

      Pravda je, že ve svých použitích to mám podobně (včetně abstraktní třídy), protože je to poměrně typický use-case – tímto zápisem generik umožňujeme vynutit nějaké chování na úrovni potomků a tím pádem by naše třída měla být pouze jako abstraktní předek, ze kterého se dědí. Ale určitě mohou být i další usecasy, kdy chceme mít už i předka neabstraktního.

  2. Neco podobneho jsem resil pri vytvareni obecneho nodu ve strome, kdy jsem chtel zajistit, aby deti byly stejneho typu jako definovany node (selftype), a take, aby parent byl stejneho typu. Zaroven zachovat typovou bezpecnost a dedeni (genericky typ nahradit potomkem, ktery ma navic nejake atributy):

  3. No jo, zmizely. Tak ještě jednou:

    @SuppressWarnings(„unchecked“)
    <T extends AbstractParent> T getMe() {
    return (T) this;
    }

    Jinak ten příklad, který uvádíš, neprojde. V tomto ohledu to samozřejmě na Tvoje řešení nemá.

  4. Ad) Zdeněk Troníček – z příkladu úplně nechápu, jak zajistíš to odvození typu na potomka – tj. aby bez castování prošel zápis:

    new Bar().addText(„Hello „).addText(„world!“).makeLowerCase().buildString();

    Ta volání addText by se v tvém případě vyhodnotila na AbstractParent, kde ta metoda makeLowerCase() chybí.

    Nebo jsem to jen špatně pochopil? Nezmizely ti generiky při přidávání komentáře?

  5. Častěji používám generickou metodu, protože je jednodušší:

    @SuppressWarnings(„unchecked“)
    T getMe() {
    return (T) this;
    }

    Hodí se to však pouze pro případy, kdy potomci o sobě nevědí, protože je možné toto:

    public class Bar extends AbstractParent {

    public Bar makeLowerCase() {
    return getMe();
    }

    public Foo m() {
    return getMe();
    }
    }

    Volání m() pak pochopitelně skončí výjimkou.

  6. Taky to na pár místech používáme. Je to fajn trik. Akorát když pak vedle této hierarchie vznikne nějaká paralelní (např. AbstractParentFactory, FooFactory, BarFactory), zatáhnou se generiky i do ní a pak jsou všechny třídy z obou hierarchií parametrizovány dvěma typovými parametry, jedním z každé hierachie. Což je někdy na škodu čitelnosti, ale pořád je zachována typová bezpečnost.

  7. Je dobré si pamatovat, že přesně touhle konstrukcí je definováno java.lang.Enum. Pak už se to hledá snadno 🙂