stringtranslate.com

это-а

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

Например, кошка «является» животным, но не наоборот. Все кошки являются животными, но не все животные являются кошками. Поведение, относящееся ко всем животным, определяется в классе животных, тогда как поведение, относящееся только к кошкам, определяется в классе кошек. Определяя класс кошек как «расширение» класса животных, все кошки «наследуют» поведение, определенное для животных, без необходимости явно кодировать это поведение для кошек.

Связанные концепции

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

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

Примеры подтипирования

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

С++

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

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

[3]

Питон

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

класс  A :  def  do_something_a_like ( self ):  проходкласс  B ( A ):  def  do_something_b_like ( self ):  проход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 , также можно считать отдельным метатипом. [4]

>>> a  =  0 >>> тип ( a ) <тип 'int'> >>> тип ( тип ( a )) <тип 'тип'> >>> тип ( тип ( тип ( a ))) < тип ' тип'> >>> тип ( тип ( тип ( a )))) <тип 'тип'>

Ява

В Java отношение между параметрами типа одного класса или интерфейса и параметрами типа другого определяется предложениями extends и implements .

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

интерфейс  PayloadList < E , P > расширяет List <E> { void setPayload ( int index , P val ) ; ... }          

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

PayloadList < Строка , Строка > PayloadList < Строка , Целое число > PayloadList < Строка , Исключение >   

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

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

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

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

С точки зрения программирования класс Square может быть реализован путем наследования от класса 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 ); }                     

Однако это нарушает LSP, даже несмотря на то, что между Rectangle и Square сохраняется связь is-a .

Рассмотрим следующий пример, в котором функция g не работает, если передан квадрат, и поэтому можно считать, что принцип открытости-закрытости нарушен.

void g ( Rectangle & r ) { r.SetWidth ( 5 ) ; r.SetHeight ( 4 ) ; assert ( r.GetArea ()) == 20 ) ; // утверждение не будет выполнено }        

И наоборот, если учесть, что тип фигуры должен быть ограничением только на соотношение ее размеров, то предположение в g() о том, что SetHeight изменит высоту и площадь, но не ширину, является недействительным не только для настоящих квадратов, но и потенциально для других прямоугольников, которые могут быть закодированы таким образом, чтобы сохранять площадь или соотношение сторон при изменении высоты.

[6]

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

Примечания

  1. ^ "Подтипы и подклассы" (PDF) . MIT OCW . Получено 2 октября 2012 г. .
  2. ^ См. также Сдерживание (компьютерное программирование) .
  3. ^ Митчелл, Джон (2002). "10 "Концепции в объектно-ориентированных языках"". Концепции в языке программирования . Кембридж, Великобритания: Cambridge University Press. стр. 287. ISBN 0-521-78098-5.
  4. ^ Гвидо ван Россум. "Подтипирование встроенных типов" . Получено 2 октября 2012 г.
  5. ^ Лисков, Барбара (май 1988). Абстракция данных и иерархия (PDF) . Уведомления SIGPLAN. Архивировано из оригинала 21 июня 2020 г.{{cite book}}: CS1 maint: unfit URL (link)
  6. ^ "The Liskov Substitution Principle" (PDF) . Роберт С. Мартин, 1996. Архивировано из оригинала (PDF) 5 сентября 2015 года . Получено 2 октября 2012 года .

Ссылки