Чем наследование отличается от подтипа?

15

С точки зрения языка программирования, что означает подтип? Я слышал, что «Наследование - это не подтип». Тогда каковы различия между наследованием и подтипом?

RoboAlex
источник
6
Интересно, может ли этот вопрос (и другие подобные ему) быть перенаправлен на новый сайт cs.SE, когда он войдет в публичную бета-версию?
Суреш Венкат
1
Добро пожаловать на cstheory, сайт вопросов и ответов по исследовательским вопросам теоретической информатики (TCS). Ваш вопрос не является вопросом исследовательского уровня в TCS. Пожалуйста, смотрите FAQ для получения дополнительной информации о том, что подразумевается под этим и предложения для сайтов, которые могут приветствовать ваш вопрос. Наконец, если ваш вопрос закрыт из-за того, что он выходит за рамки, и вы считаете, что можете отредактировать вопрос, чтобы сделать его вопросом исследовательского уровня, не стесняйтесь делать это. Закрытие не является постоянным и вопросы могут быть вновь открыты, проверьте FAQ для получения дополнительной информации.
Каве
3
@UdayReddy: Ни один вопрос не был тривиальным при первом ответе, но мы должны принять решение с современной точки зрения. Тот же аргумент, что и у вас, будет означать, что вопрос об алгоритме Дейкстры является тематическим, потому что в первой статье говорится об этом и больше ничего.
Tsuyoshi Ito
3
@ TsuyoshiIto Аналогия неуместна, потому что первая статья Дейкстры решила проблему, тогда как первая статья Карделли здесь создала проблему. Тем не менее, я понимаю, что мы не измеряем уровень техники на основе первой статьи. Позвольте мне заверить вас, что различия между наследованием и подтипом не представляют собой решенную проблему, и я ожидаю, что этот вопрос будет обсуждаться как минимум еще 20 лет. Спрашивающему может быть рекомендовано сделать дополнительную домашнюю работу и отредактировать вопрос, чтобы прояснить проблемы на уровне исследования.
Uday Reddy
3
В любом случае достаточно просто указать ФП на одноименную статью Кука и др.: Citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.102.8635
Андреас Россберг,

Ответы:

18

[Я не задумывался о проблемах объектно-ориентированных систем типов, но я скажу то, что знаю, чтобы начать обсуждение.]

Мы говорим, что является подтипом если все значения типа могут использоваться в каждом контексте, где ожидаются значения типа. Или, иначе говоря, -typed значение может «маскироваться» в качестве -typed значения.B A B A BABABAB

Если такое маскирование не создает проблем с проверкой типов, т. Е. Подключение значений типа где требуются значения типа , продолжает проверку типа, мы называем это «структурным подтипом» . Если это не вызывает проблем с поведением, то есть такое подключение не изменяет ожидаемое поведение, тогда мы называем это «поведенческим подтипом» . («Ожидаемое поведение» должно быть оформлено отдельно, и возможны многие понятия поведения.)BAB

Структурный подтип не обеспечивает поведенческий подтип, потому что структура типа может совпадать по случайным причинам. Однако определить ожидаемое поведение непросто. Таким образом, многие языки программирования используют промежуточную точку, где пользователь должен объявить, какой тип является подтипом какого. Это называется «номинальным подтипом» . Смотрите вопрос о неявном и явном подтипированиидля обсуждения этого вопроса. Идея состоит в том, что программист должен обеспечить поведенческие подтипы для всех объявленных подтипов, используя свою изобретательность. Язык не может предложить никакой помощи. Однако все объявленные подтипы должны быть как минимум структурными подтипами. В противном случае программа не сможет проверить тип. Язык может помочь обеспечить это. (Некоторые языки программирования не имеют достаточно хороших систем типов, чтобы гарантировать это во время компиляции. Если это так, то сбой типа будет обнаружен во время выполнения, или, возможно, могут быть получены неправильные результаты. Такие дыры в типах явно нежелательны.)

Когда кто-то определяет подклассы в объектно-ориентированных программах, он обычно добавляет публично видимые поля (или методы). В большинстве языков программирования такие подклассы рассматриваются как номинальные подтипы. Вопрос в том, являются ли они также структурными подтипами. Если это не так, т.е. язык программирования позволяет объявлять номинальные подтипы, которые не являются структурными, то в языке программирования могут быть дыры типов.

В простых случаях добавление полей работает нормально. Тип суперкласса ожидает меньше полей, чем тип подкласса. Таким образом, если вы подключите экземпляр подкласса, где ожидается экземпляр класса sueprclass, программа просто проигнорирует предоставленные дополнительные поля, и ничего не пойдет не так.

Однако, если у суперкласса или подкласса есть методы, которые принимают аргументы того же типа, что и он сам, или возвращают результаты того же типа, что и он сам, тогда возникают проблемы. Тогда тип интерфейса подкласса не является структурным подтипом подкласса суперкласса. Широко используемые типобезопасные языки программирования, такие как Java, не допускают таких подклассов. Таким образом, они ограничивают язык для обеспечения безопасности типов. Говорят, что язык программирования Eiffel пожертвовал безопасностью типов, чтобы добиться гибкости . Если кто-то разрабатывает сильную систему типов, которая сохраняет гибкость, он должен отказаться от принципа, согласно которому подклассы порождают подтипы. Отсюда и название статьи «Наследование не подтип», Авторы предлагают другое понятие подтипа высшего порядка, которое работает вместо этого. У Ким Брюса также есть тесно связанное предложение под названием «сопоставление», которое достигает того же эффекта. Смотрите эту презентацию . Также полезным является документ с изложением позиции Эндрю Блэка.

Сообщество семантики, вероятно, виновато в том, что в значительной степени игнорирует проблему. Мы традиционно рассматривали это как практическую проблему системного проектирования, которая не представляет большого теоретического интереса. Если это не так и в этой области действительно есть какая-то семантика, я надеюсь, что другие люди упомянут о них.

Удай Редди
источник
1
Возможно, также стоит упомянуть, что существуют реальные языки, которые успешно отделили подтипы от наследования, например, Ocaml в своей объектной системе.
Андреас Россберг
@AndreasRossberg Действительно, OCaml не было в моем кадре, когда я написал этот ответ. Я полагаю, у OCaml вообще нет номинального подтипа. Таким образом, некоторые из этих проблем не возникнут. Но есть вероятность, что типы могут совпадать случайно, даже если поведение не совпадает, и система типов не сможет помочь обнаружить ошибки такого рода.
Uday Reddy