Это - Is-a

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

В это отношения должны быть противопоставлены имеет (имеет или же имеет) отношения между типами (классами); запутывая отношения имеет и это это распространенная ошибка при разработке модели (например, компьютерная программа ) реальных отношений между объектом и его подчиненным. В это отношения также могут быть противопоставлены экземпляр отношения между объектами (экземплярами) и типами (классами): см. "различие типа-токена " и "отношения типа-лексема."[3]

Подводя итог отношениям, можно выделить:

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

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

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

C ++

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

учебный класс А{ общественный:   пустота DoSomethingALike() const {}};учебный класс B : общественный А{ общественный:   пустота Сделать что-то() const {}};пустота UseAnA(А const& some_A){   some_A.DoSomethingALike();}пустота SomeFunc(){   B б;   UseAnA(б); // b можно заменить на A.}

[5]

Python

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

учебный класс А:    def do_something_a_like(себя):        проходитьучебный класс B(А):    def do_something_b_like(себя):        проходитьdef use_an_a(some_a):    some_a.do_something_a_like()def some_func():    б = B()    use_an_a(б)  # b можно заменить на A.

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

>>> а = 0>>> тип(а)<type 'int'>>>> тип(тип(а))<type 'type'>>>> тип(тип(тип(а)))<type 'type'>>>> тип(тип(тип(тип(а))))<type 'type'>

Ява

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

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

интерфейс PayloadList<E, п> расширяет Список<E> {    пустота setPayload(int индекс, п вал);    ...}

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

PayloadList<Нить, Нить>PayloadList<Нить, Целое число>PayloadList<Нить, Исключение>

Принцип подстановки Лискова

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

пустота DrawShape(const Форма& s){  если (типичный(s) == типичный(Квадрат))    DrawSquare(static_cast<Квадрат&>(s));  еще если (типичный(s) == типичный(Круг))    DrawCircle(static_cast<Круг&>(s));}

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

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

учебный класс Прямоугольник{  общественный:    пустота   SetWidth(двойной ш)  { itsWidth = ш; }    пустота   SetHeight(двойной час) { itsHeight = час; }    двойной GetHeight() const   { возвращаться itsHeight; }    двойной GetWidth() const    { возвращаться itsWidth; }  частный:    двойной itsWidth;    двойной itsHeight;};

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

общественный учебный класс Квадрат : Прямоугольник{  общественный:    виртуальный пустота SetWidth(двойной ш);    виртуальный пустота SetHeight(двойной час);};пустота Квадрат::SetWidth(двойной ш){    Прямоугольник::SetWidth(ш);    Прямоугольник::SetHeight(ш);}пустота Квадрат::SetHeight(двойной час){    Прямоугольник::SetHeight(час);    Прямоугольник::SetWidth(час);}

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

пустота грамм(Прямоугольник& р){  р.SetWidth(5);  р.SetHeight(4);  утверждать(р.GetWidth() * р.GetHeight()) == 20);}

[8]

Смотрите также

Примечания

  1. ^ Видеть Принцип подстановки Лискова.
  2. ^ «Подтипы и подклассы» (PDF). MIT OCW. Получено 2 октября 2012.
  3. ^ Отношения типа и токена
  4. ^ Смотрите также Сдерживание (компьютерное программирование).
  5. ^ Митчелл, Джон (2002). «10» понятий в объектно-ориентированных языках"". Понятия на языке программирования. Кембридж, Великобритания: Издательство Кембриджского университета. п. 287. ISBN  0-521-78098-5.
  6. ^ Гвидо ван Россум. «Подтипирование встроенных типов». Получено 2 октября 2012.
  7. ^ Лисков, Варвара (май 1988 г.). Абстракция данных и иерархия (PDF). Уведомления SIGPLAN.
  8. ^ «Принцип замещения Лискова» (PDF). Роберт С. Мартин, 1996. Архивировано из оригинал (PDF) 5 сентября 2015 г.. Получено 2 октября 2012.

Рекомендации