Přeskočit na obsah

Je speciálním případem

Z Wikipedie, otevřené encyklopedie

Je speciálním případem, je druhem, je typem, anglicky is-a je v ontologii a reprezentaci znalostí[pozn. 1], v objektově orientovaném programování a objektově orientované analýze a návrhu je subsumpční[pozn. 2] vztah mezi abstrakcemi (například, typy, třídami), kdy jedna třída A je podtřídou jiné třídy B (a tedy B je nadtřídou třídy A). Jinými slovy typ A je podtypem typu B, jestliže specifikace A implikuje specifikaci B. Tj. libovolný předmět (nebo třída), který vyhovuje specifikaci A, vyhovuje také specifikaci B, protože specifikace B je slabší.[1]

Například kočka je speciálním případem zvířete, ale ne naopak. Všechny kočky jsou zvířata, ale ne všechna zvířata jsou kočky. Chování, které je relevantní pro všechna zvířata, je definováno na třídě zvířat, zatímco chování, které je relevantní pouze pro kočky, je definováno na třídě koček. Definováním třídy koček jako specializace třídy zvířat všechny kočky zdědí chování definované pro zvířata, aniž by bylo nutné toto chování pro kočky explicitně uvádět.

Příbuzné koncepty

[editovat | editovat zdroj]

Vztah je speciálním případem (is-a je třeba rozlišovat od vztahu mít něco (has a mezi typy (třídami); zaměňování těchto dvou vztahů je častou chybou při navrhování modelu (například počítačového programu) skutečného vztahu mezi objektem a jeho podřízeným. Vztah je speciálním případem se také liší od vztahu je instancí mezi objekty (instancemi) a typy (třídami): viz Rozlišování typu a entity.

Shrneme-li vztahy, pak jsou to:

  • hyperonymumhyponymum (nadtyp/nadtřída–podtyp/podtřída) relace mezi typy (třídy) definování taxonomic hierarchie, kde
    • pro subsumption relace: hyponymum (podtyp, podtřída) je ve vztahu je speciálním případem (is-a) se svým hyperonymem (nadtypem, nadtřídou);
  • holonymummeronymum (celek/entity/kontejner–část/konstituent/člen) vztahy mezi typy (třídami) definujícími hierarchii vlastnění, kde
    • pro relaci agregace (tj. bez vlastnictví):
      • holonymum (celý) je ve vztahu se svým meronymem (částí),
    • pro skládání (tj. s vlastnictví) relace:
      • meronymum (konstituent) je ve vztahu je částí se ho holonymem (entity),
    • pro containment[2] relace:
      • meronymum (člen) je ve vztahu je členem se svým holonymem (kontejnerem);
  • koncept–předmět (typ–token) relace mezi typy (třídami) a objekty (instancemi), kde
    • token (předmět) je ve vztahu je instancí se svým typem (třídou).

Příklady podtypování

[editovat | editovat zdroj]

Podtypování umožňuje nahradit jeden typ jiným typem nebo abstrakci. Říkáme, že podtypování vytváří vztah je speciálním případem mezi podtypem a nějakou existující abstrakcí, a to buď implicitně anebo explicitně, v závislosti na podpoře jazyka. V jazycích podporujích dědičnost jako mechanismus podtypování lze tento vztah vyjádřit explicitně prostřednictvím dědičnosti.

Následující kód v jazyce C++ vytváří explicitní vztah dědičnosti mezi třídami B a A, kde B je jak podtřídou i tak podtypem třídy A, a může být použita jako třída A všude tam, kde je uvedena třída B (prostřednictvím reference, ukazatele nebo samotného objektu).

class A
{ public:
   void DoSomethingALike() const {}
};

class B : public A
{ public:
   void DoSomethingBLike() const {}
};

void UseAnA(A const& some_A)
{
   some_A.DoSomethingALike();
}

void SomeFunc()
{
   B b;
   UseAnA(b); // b can be substituted for an A.
}

[3]

Následující kód v jazyce Python vytváří explicitní vztah dědičnosti mezi třídami B and A, kde B je jak podtřídou i tak podtypem třídy A, a může být použita jako třída A všude tam, kde je vyžadována třída B.

class A:
    def do_something_a_like(self):
        pass

class B(A):
    def do_something_b_like(self):
        pass

def use_an_a(some_a):
    some_a.do_something_a_like()

def some_func():
    b = B()
    use_an_a(b)  # b can be substituted for an A.

V následujícím příkladě je type(a) „běžný“ typ a type(type(a)) je metatyp. Ačkoli všechny typy, tak jak jsou distribuované, mají stejný metatyp PyType_Type, který je zároveň vlastním metatypem), není to podmínkou. Typ klasických tříd, známý jako types.ClassType, lze také považovat za samostatný metatyp.[4]

>>> a = 0
>>> type(a)
<type 'int'>
>>> type(type(a))
<type 'type'>
>>> type(type(type(a)))
<type 'type'>
>>> type(type(type(type(a))))
<type 'type'>

V jazyce Java se vztah je speciálním případem mezi typovými parametry jedné třídy nebo rozhraní a typovými parametry jiné třídy určuje pomocí klauzulí extends a implements.

Pomocí tříd Collections implementuje ArrayList<E> třídu List<E>, a List<E> rozšiřuje Collection<E>. ArrayList<String> je tedy podtypem typu List<String>, který je podtypem typu Collection<String>. Vztah podtypování se mezi typy zachovává automaticky. Při definici rozhraní PayloadList, které ke každému prvku přiřazuje volitelnou hodnotu generického typu, může jeho deklarace vypadat takto:

interface PayloadList<E, P> extends List<E> {
    void setPayload(int index, P val);
    ...
}

Následující parameterizace typu PayloadList jsou podtypy typu List<String>:

PayloadList<String, String>
PayloadList<String, Integer>
PayloadList<String, Exception>

Liskovové princip zastoupení

[editovat | editovat zdroj]
Podrobnější informace naleznete v článku Liskovové princip zastoupení.

Liskovové princip zastoupení (LSP) vysvětluje vlastnost „Jestliže pro každý objekt o1 typu S existuje objekt o2 typu T takový, že pro všechny programy P definované v termínech T se chování P nezmění, když je o1 nahrazeno o2, pak S je podtypem T“,[5]

Následující příklad ukazuje narušení Liskovové principu zastoupení.

class Rectangle
{
  public:
    void   SetWidth(double w)  { itsWidth = w; }
    void   SetHeight(double h) { itsHeight = h; }
    double GetHeight() const   { return itsHeight; }
    double GetWidth() const    { return itsWidth; }
    double GetArea() const     { return GetHeight() * GetWidth(); }
  private:
    double itsWidth;
    double itsHeight;
};

Z programátorského hlediska lze třídu Square implementovat děděním z třídy Rectangle.

public class Square : Rectangle
{
  public:
    virtual void SetWidth(double w);
    virtual void SetHeight(double h);
};
void Square::SetWidth(double w)
{
    Rectangle::SetWidth(w);
    Rectangle::SetHeight(w);
}
void Square::SetHeight(double h)
{
    Rectangle::SetHeight(h);
    Rectangle::SetWidth(h);
}

To však porušuje LSP, přestože mezi obdélníkem Rectangle a čtverecem Square platí vztah je speciálním příkadem.

Uvažujme následující příklad, kde funkce g nefunguje, pokud je předán Čtverec, a tak by se dalo uvažovat o porušení principu otevřeného-uzavřeného.

void g(Rectangle& r)
{
  r.SetWidth(5);
  r.SetHeight(4);
  assert(r.GetArea()) == 20); // assertion will fail
}

Opačně, pokud uvažujeme, že typ tvaru by měl být pouze omezením na vztah jeho rozměrů, pak předpoklad v g(), že SetHeight změní výšku a plochu, ale ne šířku, který je neplatný, ne pouze pro skutečné čtverce, ale dokonce potenciálně i pro jiné obdélníky, které by mohly být kódovány tak, aby při změnách výšky zachovávaly plochu nebo poměr stran.

[6]

V tomto článku byl použit překlad textu z článku is-a na anglické Wikipedii.

  1. Subtypes and Subclasses [online]. MIT OCW [cit. 2012-10-02]. Dostupné online. 
  2. Viz též objektová kompozice.
  3. MITCHELL, John. Concepts in programming language. Cambridge, UK: Cambridge University Press, 2002. ISBN 0-521-78098-5. Kapitola 10 "Concepts in object-oriented languages", s. 287. 
  4. Guido van Rossum. Subtyping Built-in Types [online]. [cit. 2012-10-02]. Dostupné online. 
  5. LISKOV, Barbara. Data Abstraction and Hierarchy. [s.l.]: SIGPLAN Notices, May 1988. Dostupné v archivu pořízeném z originálu dne 2020-06-21. 
  6. The Liskov Substitution Principle [online]. Robert C. Martin, 1996 [cit. 2012-10-02]. Dostupné v archivu pořízeném dne 2015-09-05. 

Literatura

[editovat | editovat zdroj]
  • BRACHMAN, Ronald J., 1983. What IS-A is and isn't. An Analysis of Taxonomic Links in Semantic Networks. IEEE Computer. Říjen 1983, roč. 16, čís. 10. Dostupné online. 
  • HAINAUT, Jean-Luc; HICK, Jean-Marc; ENGLEBERT, Vincent; HENRARD, Jean; ROLAND, Didier, 1996. Understanding Implementations of IS-A Relations]. ER 1996: 42-57. [s.l.]: [s.n.]. S. 42–57. 

Související články

[editovat | editovat zdroj]