Is-a

редактировать

В представление знаний, объектно-ориентированное программирование и дизайн (см. объектно-ориентированная программная архитектура ), is-a (is_a или is a ) является подчинением связь между абстракциями (например, типы, классы ), при этом один класс A является подклассом из другой класс B (и поэтому B является суперклассом класса A). Другими словами, тип A является подтипом типа B, когда спецификация A подразумевает спецификацию B. То есть любой объект (или класс), который удовлетворяет спецификации A, также удовлетворяет спецификации B, потому что спецификация B слабее.

Отношение is-a должно контрастировать с has-a (has_a или имеет) связь между типами (классами); путаница в отношениях has-a и is-a - распространенная ошибка при разработке модели (например, компьютерной программы ) реальных отношений между объектом и его подчиненным. Отношение is-a также можно противопоставить отношениям instance-of между объектами (экземплярами) и типами (классами): см. «различие токена типа » и «отношения типа-лексема."

Чтобы обобщить отношения, существуют:

  • гипероним - гипоним (супертип – подтип) отношения между типами (классами), определяющие таксономическую иерархию, где
    • для отношения подчинения : гипоним (подтип, подкласс) имеет отношение типа (является) со своим гиперонимом (супертип, суперкласс);
  • холоним - мероним (целое / сущность / часть-контейнер / составной элемент / член) отношения между типами (классами), определяющие притяжательную иерархию, где
    • для агрегации (т. Е. Без владения) отношение:
      • холоним (целое) имеет отношение has-a со своим меронимом (частью),
    • для отношения состава (т.е. с отношением собственности):
      • мероним (составляющая) имеет отношение часть со своим холонимом (сущностью),
    • для содержащего t отношение:
      • мероним (член) имеет отношение со своим холонимом (контейнер );
  • понятие-объект (тип-токен) отношения между типами (классами) и объектами (экземплярами), где
    • токен (объект) имеет отношение экземпляр со своим типом (классом).

Содержание

  • 1 Примеры подтипов
    • 1.1 C ++
    • 1.2 Python
    • 1.3 Java
  • 2 Принцип подстановки Лискова
  • 3 См. Также
  • 4 Примечания
  • 5 Ссылки

Примеры подтипов

Подтипы позволяют заданному типу быть заменен другим типом или абстракцией. Говорят, что подтипирование устанавливает связь is-a между подтипом и некоторой существующей абстракцией, неявно или явно, в зависимости от поддержки языка. Отношения могут быть явно выражены через наследование на языках, которые поддерживают наследование как механизм подтипа.

C ++

Следующий код C ++ устанавливает явное отношение наследования между классами B и A, где B - оба подкласс и подтип A, и могут использоваться как A везде, где указан B (через ссылку, указатель или сам объект).

класс A {public: void DoSomethingALike () const {}}; класс B: общественность A {public: void DoSomethingBLike () const {}}; void UseAnA (A const some_A) {some_A.DoSomethingALike (); } void SomeFunc () {B b; UseAnA (b); // b можно заменить на A.}

Python

Следующий код Python устанавливает явное отношение наследования между классами Bи A, где Bявляется подклассом и подтипом Aи может использоваться как Aвезде, где требуется B.

класс 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 можно заменить на A.

В следующем примере type (a)является «обычным» типом, а type (type (a))является метатип. В то время как распределенные все типы имеют один и тот же метатип (PyType_Type, который также является его собственным метатипом), это не является требованием. Тип классических классов, известный как types.ClassType, также можно рассматривать как отдельный метатип.

>>>a = 0>>>type (a) >>>type ( type (a)) >>>type (type (type (a))) >>>type (type (type (type (a)))) 

Java

В Java - это связь между параметрами типа одного класса или интерфейса и параметрами типа другого, которые определяются предложениями extends и реализует.

Используя классы Collections, ArrayList реализует List , а List расширяет Collection . Итак, ArrayList - это подтип List , который является подтипом Collection . Отношение подтипов сохраняется между типами автоматически. При определении интерфейса PayloadList, который связывает необязательное значение универсального типа P с каждым элементом, его объявление может выглядеть так:

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

Следующие параметризации PayloadList являются подтипами List :

PayloadList PayloadList PayloadList 

Принцип замещения Лискова

Принцип замещения Лискова объясняет свойство: «Если для каждому объекту o1 типа S соответствует объект o2 типа T, так что для всех программ P, определенных в терминах T, поведение P не меняется, когда o1 заменяется на o2, тогда S является подтипом T, ". В следующем примере показано нарушение LSP.

void DrawShape (const Shape s) {if (typeid (s) == typeid (Square)) DrawSquare (static_cast (s)); иначе, если (typeid (s) == typeid (Circle)) DrawCircle (static_cast (s)); }

Очевидно, функция DrawShape плохо отформатирована. Он должен знать обо всех производных классах класса Shape. Кроме того, его следует менять всякий раз, когда создается новый подкласс Shape. В объектно-ориентированном дизайне многие рассматривают структуру этого как анафему.

Вот более тонкий пример нарушения LSP:

class Rectangle {public: void SetWidth (double w) {itsWidth = w; } void SetHeight (двойной h) {itsHeight = h; } double GetHeight () const {return itsHeight; } double GetWidth () const {return itsWidth; } private: удвоить itsWidth; удвоить itsHeight; };

Это работает хорошо, но когда дело доходит до класса Square, который наследует класс Rectangle, он нарушает LSP, даже несмотря на то, что отношение is-a сохраняется между Rectangle и Square. Потому что квадрат прямоугольный. В следующем примере переопределяются две функции, Setwidth и SetHeight, для устранения проблемы. Но исправление кода означает, что конструкция неисправна.

открытый класс Square: Rectangle {public: virtual void SetWidth (double w); виртуальная пустота SetHeight (двойной h); }; void Square :: SetWidth (двойной ш) {Прямоугольник :: SetWidth (ш); Прямоугольник :: SetHeight (ш); } void Square :: SetHeight (двойной h) {Rectangle :: SetHeight (h); Прямоугольник :: SetWidth (h); }

В следующем примере функция g работает только для класса Rectangle, но не для Square, поэтому принцип открыт-закрытость был нарушен.

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

См. Также

Notes

Ссылки

Последняя правка сделана 2021-05-24 07:11:38
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте