A tudásreprezentációban, objektum-orientált programozásban és tervezésben (lásd objektum-orientált program architektúra ), az-egy (is_a vagy az-egy) egy absztrakciók közötti alárendelt kapcsolat (pl típusok, osztályok ), ahol az egyik osztály, A, egy másik osztály, B, alosztálya (és így B superclass-a az A-nak). Más szavakkal, az A típus a B típus altípusa, amikor A specifikációja magában foglalja B specifikációját. Vagyis bármely olyan objektum (vagy osztály), amely megfelel az A specifikációjának, szintén megfelel a B specifikációnak, mert B specifikációja gyengébb.[1]

Az az-egy kapcsolat ellentétben áll a van-egy ( has_a vagy a ) kapcsolattal a típusok (osztályok) között; összekeverni a van-egy és az-egy kapcsolatokat gyakori hiba, amikor modellt szerkesztünk (pl számítógépes program ) az objektum és az alárendelt valós kapcsolatáról. Az az-egy viszony ellentétben állhat az objektumok (példányok) és a típusok (osztályok) közötti instance-of kapcsolattal is: lásd " típus-token megkülönböztetés " és " típus-token kapcsolatok ".[2]

Összegezve a kapcsolatokat, van

  • hiperonim - hyponym ( szupertípus – altípus) kapcsolatok a típusok (osztályok) között, meghatározva egy taxonómiai hierarchiát, ahol
    • szubupupciós viszony esetén: a hiponím (altípus, alosztály) type-of ( az-egy ) összefüggésben van hiperonimájával (szupertípus, szuperosztály);
  • holonym - meronym (teljes / entitás / konténer-rész / alkotóelem / tag) típusok (osztályok) közötti kapcsolatok, amelyek egy birtokló hierarchiát határoznak meg, ahol
    • összesítő (vagyis tulajdonjog nélküli) kapcsolat esetén:
      • egy (teljes) holonymnak van-egy kapcsolata van a meronimával (részleges),
    • összetétel (azaz tulajdonosi) kapcsolat esetén:
      • egy meronima (alkotóelem) part-of kapcsolata vana a holonimjával (entitásával),
    • az elszigetelés [3] kapcsolatához:
      • egy meronym (tag) van egy member-of kapcsolata van a holonimjával ( konténer );
  • concept-object (típus-token) kapcsolat van a típusok (osztályok) és az objektumok (példányok) között, ha
    • egy tokennek (objektumnak) egy instance-of kapcsolata van a típusával (osztályával).

Példák az altípusokra szerkesztés

A subtyping lehetővé teszi, hogy egy adott típust váltson egy másik típus vagy absztrakció. A subtyping létrehoz egy az-egy kapcsolatot az altípus és néhány meglévő absztrakció között, vagy explicit vagy implicit módon,nyelvi támogatástól függően.A kapcsolatot ki lehet fejezni örökléssel, azon nyelvek esetén, amik támogatják azt, mint subtyping mechanism.

C ++ szerkesztés

Az alábbi C ++ kód létrehoz egy kifejezett öröklés kapcsolatot a B és A osztályok között, amelyben B jelentése egyaránt egy alosztálya, és egy altípusa A-nak, és fel lehet használni, mint egy A-t, ahol egy B van megadva (egy referenciával, egy mutatóval vagy objectként ).

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.
}

[4]

Python szerkesztés

A következő python kódot hoz létre explicit öröklés közötti kapcsolat osztályok B és A B ahol egyszerre alosztály és altípusa A és fel lehet használni, mint egy A ahol a B van szükség.

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.

A következő példa szerint a type(a) "normál", és az type(type(a)) egy metatípus. Míg eloszlatva az összes típusnak azonos metatípusa van ( PyType_Type, amely szintén a saját metatípusa), ez nem követelmény. A klasszikus osztályok típusa, az úgynevezett types. ClassType különálló metatípusnak is tekinthető.[5]

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

Java szerkesztés

Java-ban az az-egy kapcsolat egy osztály vagy interfész típusparamétereinek és egy másik típusparamétereinek kapcsolatát a kiterjesztések és az implementációs záradékok határozzák meg.

A Gyűjtemény osztályok használatával az ArrayList <E> megvalósítja az List<E>-t , és az <E> Lista kiterjeszti a Collection<E>-t . Tehát az ArrayList <String> a <String> lista altípusa, amely a Collection<String> altípusa. Az altípus-kapcsolat automatikusan megmarad a típusok között. Amikor meghatározunk egy interfészt, a PayloadList-t, amely egyesíti a P típusú általános opcionális értéket az egyes elemekkel, akkor annak deklarálása a következőképpen nézhet ki:

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

A PayloadList következő paraméterei a List<String> altípusai:

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

Liskov-helyettesítési elv szerkesztés

A Liskov-helyettesítési elv magyarázatot ad egy tulajdonságra: "Ha minden S típusú o1 objektumhoz van egy T típusú o2 objektum, oly módon, hogy a T-vel definiált valamennyi P programnál P viselkedése nem változik, ha o1 helyett o2 van, akkor S "a T altípusa" .[6] A következő példa az LSP megsértését mutatja.

void DrawShape(const Shape& s)
{
  if (typeid(s) == typeid(Square))
    DrawSquare(static_cast<Square&>(s));
  else if (typeid(s) == typeid(Circle))
    DrawCircle(static_cast<Circle&>(s));
}

Nyilvánvaló, hogy a DrawShape funkció rosszul formázva van. A Shape osztály minden derivatív osztályáról tudnia kell. Ezenkívül meg kell változtatni, amikor a Shape új alosztálya jön létre. Objektum-orientált tervezésben ezt a struktúrát tekintjük anatémának. Íme egy finomabb példa az LSP megsértésére:

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; }
  private:
    double itsWidth;
    double itsHeight;
};

Ez jól működik, de a négyzet osztálynál, amely a Téglalap osztályt örököli, megsérti az LSP-t, annak ellenére, hogy fennáll az az-egy kapcsolat a Téglalap és a Négyzet között. Mert a négyzet téglalap alakú. A következő példa felülírja a probléma megoldásához két funkciót, a Setwidth és a SetHeight funkciókat. A kód javítása azonban azt jelenti, hogy a tervezés hibás.

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);
}

A következő példa szerint a g függvény csak a téglalap osztályra működik, de a négyzetre nem, és így megsértették a nyitott-zárt alapelvet.

void g(Rectangle& r)
{
  r.SetWidth(5);
  r.SetHeight(4);
  assert(r.GetWidth() * r.GetHeight()) == 20);
}

Kapcsolódó szócikkek szerkesztés

Megjegyzések szerkesztés

  1. Subtypes and Subclasses. MIT OCW. (Hozzáférés: 2012. október 2.)
  2. Type–token relations
  3. See also Containment (computer programming).
  4. Mitchell, John. 10 "Concepts in object-oriented languages", Concepts in programming language. Cambridge, UK: Cambridge University Press, 287. o. (2002). ISBN 0-521-78098-5 
  5. Guido van Rossum: Subtyping Built-in Types. (Hozzáférés: 2012. október 2.)
  6. Liskov, Barbara. Data Abstraction and Hierarchy. SIGPLAN Notices (1988. május 1.) 

Irodalom szerkesztés