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 также можно противопоставить отношение экземпляра между объектами (экземплярами) и типами (классами): см. Различие типа и токена .

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

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

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

С++

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

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

[3]

Питон

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

класс  A :  защита  do_something_a_like ( self ):  пройтикласс  B ( A ):  def  do_something_b_like ( self ):  пройтизащита  use_an_a ( some_a ):  some_a . сделать_что-то_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 is- отношение между параметрами типа одного класса или интерфейса и параметрами типа другого определяется предложениями расширения и реализации .

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

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

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

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

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

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

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

класс Rectangle { public : void SetWidth ( double w ) { itsWidth = w ; } void SetHeight ( двойной час ) { itsHeight = час ; } Double GetHeight () const { return itsHeight ; } Double GetWidth () const { return itsWidth ; } Double GetArea () const { return GetHeight () * GetWidth (); } Частное : удвоить свою ширину ; удвоить его высоту ; };                                              

С точки зрения программирования класс Square может быть реализован путем наследования класса Rectangle.

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

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

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

пустота г ( Прямоугольник & р ) { р . SetWidth ( 5 ); р . УстановитьВысоту ( 4 ); утверждать ( 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. ^ «Принцип замены Лискова» (PDF) . Роберт К. Мартин, 1996. Архивировано из оригинала (PDF) 5 сентября 2015 года . Проверено 2 октября 2012 г.

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