Na navigaci | Klávesové zkratky

Jak souhrnně nazývat třídy a rozhraní?

Názvoslovný oříšek: jak souhrnně označovat třídy a rozhraní? Jak třeba nazvat proměnnou, která může obsahovat jak název třídy, tak rozhraní? Co zvolit místo $class?

Dá se tomu říkat type ($type), nicméně to je zase příliš obecné, protože typem je i řetězec nebo pole. Z pohledu jazyka jím může být i něco komplikovanějšího, třeba ?array. Navíc je sporné, co je v případě objektu jeho typ: je jím název třídy, nebo je to object?

Nicméně souhrnné označení pro třídy a rozhraní skutečně existuje: je jím slovo třída.

Cože?

  1. Z pohledu deklarace je interface hodně ořezaná třída. Může obsahovat jen veřejné abstraktní metody. Což také implikuje nemožnost vytvářet objekty. Rozhraní jsou tedy podmnožinou tříd. A pokud je něco podmnožinou, tak to můžeme označovat názvem nadmnožiny. Člověk je savec, stejně jako rozhraní je třída.
  2. Nicméně je tady ještě pohled užití. Třída může dědit jen od jedné třídy, ale může implementovat vícero rozhraní. Nicméně tohle je omezení týkající se tříd, samotné rozhraní za to nemůže. Obdobně: třída nemůže dědit od final třídy, ale přitom final třídu pořád vnímáme jako třídu. A také pokud třída může implementovat víc rozhraní (tj. tříd, viz 1.), stále je vnímejme jako třídy.

A co traity? Ty sem vůbec nepatří, z hlediska OOP jednoduše neexistují.

Tedy problém se společným pojmenováním tříd a rozhraní je vyřešen. Říkejme jim prostě třídy.

classes + interfaces = classes

No jo, ale vznikl tady problém nový. Jak říkat třídám, které nejsou rozhraní? Tedy jejich doplňku. Tomu, co se ještě na začátku článku nazývalo třídy. Nerozhraní? Nebo implementations? 🙂

To je ještě větší oříšek. To je pořádný ořech. Víte co, raději zapomeňme na to, že rozhraní jsou také třídy, a tvařme se opět, že každý OOP identifikátor je buď třída, nebo rozhraní. Bude to snazší.

před 7 lety v rubrice PHP | blog píše David Grudl | nahoru

Mohlo by vás zajímat

Komentáře

  1. koubel #1

    avatar

    Traity určitě z pohledu OOP existují, jsou to v podstatě interfaces s implementací. IMHO se něco takového jako traity chystají zavést i v C# 8, klasická dědičnost ustupuje do pozadí čím dál častěji, jak se zdá.

    Jinak ale smysl postu není moc jasný, protože si nezmínil kontext. Klidně to může být nějaký implementační detail a pak to to můžu pojmenovat jak chci např. „objectTypes“ apod.

    před 7 lety
  2. Tharos #2

    avatar

    Ty jo, při vší úctě… Interface v „Javovském“ OOP vážně není třída.

    Hezky je to vysvětlené například zde.

    Očekávat v proměnné pojmenované $class název rozhraní by pro mě osobně bylo asi dost WTF…

    před 7 lety
  3. Tomas Votruba #3

    avatar

    Jedu „type“ v autowire stylu „getByType“ :).
    Object type by taky šlo, jen to je méně konvenční.

    před 7 lety | reagoval [7] David Grudl
  4. MartinMystikJonas #4

    avatar

    Podle LSP musí podtyp umět vše co nadtyp. Pokud rozhraní neumí vše co třída pak není podtypem třídy, ale naopak. Třída je rozhraní rozšířené o implementaci.

    Rozhraní – jakým voláním objekt rozumí
    Implementace – jak objekt voláním rozumí
    Třída = Rozhraní + implementace

    Za mě tedy:
    Interfaces = pure interfaces + classes

    před 7 lety | reagoval [7] David Grudl
  5. Tharos #5

    avatar

    Abych byl aspoň trochu konstruktivní, napadá mě ještě:

    contracts = interfaces + classes

    Vycházím z toho, že rozhraní je kontrakt. Třída, coby implementace, vždy implementuje nějaký kontrakt, ať už nadefinovaný „externě“ (skrze stand-alone interface), anebo nadefinovaný ad-hoc tou třídou. Z každé takové by bylo možné vyextrahovat rozhraní. Pak je tedy contract tím společným pojítkem…

    Hmm, ale jelikož kontrakt je vlastně synonymum pro rozhraní, varianta, o které píše kolega Martin výše, mi dává naprostý smysl. :)

    interfaces = pure interfaces + classes
    před 7 lety
  6. Miloslav Ponkrác #6

    Je to jen otázkou terminologie. Class, interface i trait jsou jen různé druhy tříd s rozdílnými možnostmi – z hlediska objektového programování.

    Jak Java, tak PHP neuměla konzistentně vyřešit, jak nahlížet na třídy z hlediska vícenásobné dědičnosti – jak konzistentně vyřešit u vícenásobné dědičnosti požadavek na vícenásobné dědění implementací.

    Takže se udělala třída, kterých je možné podědit několik a nazvala se rozhraním (interface). A pak se udělal třída, která smí nést implementaci, ale nesmí se podědit vícekrát a nazvala se třídou (class). A pak se navíc v PHP udělala třída, která může nést implementaci, může se dokonce vícekrát podědit, ale typově se projevuje omezeně a nazvala se v PHP trait, ve funkcionálních jazycích se nazývá běžně mixinou (mixin).

    Takže jsou to všechno třídy – jen různě očesané svými možnostmi, protože PHP nedokázalo lépe a konzistentněji zvládnou vícenásobnou dědičnost (stejně jako to nedokázala zmiňovaná Java).

    Takže třída nutně (podle OOP paradigmatu) nemusí zakládat typovou informaci. Stejně tak jako třída (class) není „rozhraní rozšířené o implemetanci“, protože není možné podědit více classes v jednom potomkovi, ale je možné podědit více interfaces.

    Takže skutečně class, interface a traits jsou všechno třídy. S různými možnostmi.

    Miloslav Ponkrác

    před 7 lety
  7. David Grudl #7

    avatar

    #3 Tomas Votruba, Nicméně poměrně často se to, díky nejasnému názvoslovní, děje, třeba i v dokumentaci (viz $class_name).

    #4 MartinMystikJonas, Moc ti nerozumím, s větou „Třída = Rozhraní + implementace“ jsme za jedno, ale jak si z toho (tj. z „class = inteface + implementation“) vyvodil „Interfaces = pure interfaces + classes“ už nechápu. Redefinuješ pojem interface?

    před 7 lety | reagoval [8] MartinMystikJonas
  8. MartinMystikJonas #8

    avatar

    #7 David Grudl, Chápu to takhle:

    1. Pokud class jako klíčové slovo jazyka označuje prvek složený z interface + implementation (rozhraní s implementací)
    2. Pokud interface jako klíčové slovo označuje prvek obsahující jen interface (rozhraní bez implementace nebo pure interface)

    Tak pokud hledám označení pro proměnou obsahující prvek jednoho nebo druhého typu tak to co tato proměnná vlastně označuje je rozhraní tohoto prvku. Proto bych to proměnou nazval interface ať už obsahuje pure interface (tedy interface ve smyslu klíčového slova jazyka) nebo rozhraní třídy (tedy interface definované společně s implementací).

    Jednoduše průnik vlastností class a interface je to že definují rozhraní (interface) nějakého objektu. Beru to z pohledu toho jak taková proměnná pak jde použít – jde použít v místech, kde podle ní potřebuju třeba určit jakým voláním to co obsahuje bude rozumět.

    před 7 lety
  9. MartinMystikJonas #9

    avatar

    Možné ještě pro přehlednost, ať ujasníme pojmy:

    INTERFACE – klíčové slovo jazyka, definice rozhraní objektu bez implementace
    CLASS – klíčové slovo jakzyka, definice rozhraní a implementace objektu

    interface – rozhraní objektu, tedy to jakým voláním rozumí
    implementation – to jakým způsobem objekt na volání reaguje

    INTERFACE = interface
    CLASS = interface + implementation

    když to otočíme tak interface je obsaženo jak v CLASS tak v INTERFACE takže:

    interface = INTERFACE || CLASS

    před 7 lety
  10. David Grudl #10

    avatar

    Aha, rozumím. Já měl na mysli spíš sjednocení, než průnik.

    před 7 lety | reagoval [11] MartinMystikJonas
  11. MartinMystikJonas #11

    avatar

    #10 David Grudl, Takže jaký je kontext použití té proměnné? Nenapadá mě žádné použití, kde bych tu proměnnou požíval ve smyslu sjednocení.

    před 7 lety | reagoval [12] David Grudl
  12. David Grudl #12

    avatar

    #11 MartinMystikJonas, už jsem to tu zmiňoval, třeba $class_name https://www.php.net/…class-of.php

    před 7 lety | reagoval [14] MartinMystikJonas
  13. Miloslav Ponkrác #13

    Pokud to nechcete nazývat třídou, tak se co svět světem stojí se už léta ustálil název „objektový typ“.

    „Interface“ není čistě rozhraní objektu, je to také typová informace o typové kompatibilitě. Dokonce v zásadě teoreticky nic podstatného nebrání tomu, aby v příští verzi PHP dovoloval „interface“ také implementaci metod.

    Objektové typy, tedy class, interface a trait řeší různé kombinace čtveřice: 1) rozhraní (API) třídy, 2) typ a typovou kompatibilitu, 3) možnost (jednoduché či vícenásobné) dědičnosti, 4) implementací.

    před 7 lety
  14. MartinMystikJonas #14

    avatar

    #12 David Grudl, Ale v tomhle případě to je přesně to o čem píšu. Použití metody is_subclass_of je v tom, že mi umožní zkontrolovat, zda daný objekt bude rozumět určitému volání. Kontroluji teda zda jeho rozhraní odpovídá interface dané CLASS nebo interface daného INTERFACE.

    To co si myslím, že hledáme je název pro rozhraní třídy ve smyslu „rozhraní objektu, tedy to jakým voláním rozumí“. Je pravda, že použití názvu interface vede ke zmatení, protože interface (rozhraní) je jak rozhraní objektu v abstraktním smyslu tak klíčové slovo INTERFACE popisující konkrétní konstrukci jazyka.

    Co jsme se ale snažil především říct je, že vidím chybu v tvrzení, že interface je podtyp třídy. Je tomu spíše naopak tedy třída je podtyp rozhraní. Přesněji řešeno CLASS i INTERFACE je interface v abstraktním smyslu. Ale nikoliv INTERFACE je CLASS.

    před 7 lety | reagoval [15] David Grudl
  15. David Grudl #15

    avatar

    #14 MartinMystikJonas, Rozhraní je v podstatě totéž, jako kompletně abstraktní třída. Tedy je speciálním případem třídy. Tedy je podmnožinou tříd.

    před 7 lety
  16. Taco #16

    avatar

    Když stojím v nějaké funkci, a chci, aby mi argumentem přišel nějaký konkrétní objekt, tak mě nezajímá, jestli ten objekt je class, nebo interface, nebo abstract class, nebo trait. A dokonce mě ani nezajímá, jakou má implementaci. Vlastně jediné, co potřebuju je, aby ten objekt měl tuto a tuto metodu a já ji mohl úspěšně zavolat.
    Pak ještě mohu řešit, že má přijít hodnota nějakého nominálního typu (to jsou takové ty interface bez metod).

    No, a na hraně toho je ten typový filtr v argumentu. Tam dám něco, co splňuje moje požadavky.

    Osobně tomu prostě říkám typ. V mém vidění světa je String nebo Integer typ uchopitelný stejným způsobem jako třeba Countable či ArrayAccess.

    před 7 lety

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.


phpFashion © 2004, 2024 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.