Тип - отношение подтипа. Что-то кажется неясным - PullRequest
6 голосов
/ 15 февраля 2010

Я читаю некоторые слайды класса на объектно-ориентированных языках программирования и вступил в определение подтипа типа:

Барбара Лисков, «Абстракция данных и иерархия», уведомления SIGPLAN, 23,5 (май 1988 года):

Что здесь нужно, так это что-то как следующая замена свойство: если для каждого объекта тип S есть объект o_T из тип T такой, что для всех программ P
определяется с точки зрения Т, поведение P не изменяется, когда o_S заменен на o_T, то S является подтип T

Затем идет пример:

Точка = {x: целое число, y: целое число}
PositivePoint = {x: положительный, y: положительный}
где положительный = {k: целое число | k> 0}

Можно ли сказать, что PositivePoint ≤ Point?

Да, потому что элемент типа PositivePoint может всегда заменить элемент типа Point в программе, определенной в Точечные условия!

Теперь ... мне кажется, что все должно быть совсем наоборот: Point ≤ PositivePoint, потому что я не мог использовать PositivePoint в программе, которая использует Point с отрицательными координатами, а я мог наоборот.

Я сомневался, был ли синтаксис Type ≤ Sub-type или Sub-Type ≤ Type, но утверждение кажется более ясным, что же тогда не так?


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

Просто чтобы упростить задачу, вопрос: Можете ли вы сказать, что PositivePoint является подтипом Point? Почему?


2-е редактирование

Я сообщаю здесь, что я написал в комментарии, надеясь, что это прояснит мою проблему:

Предположим, что программа должна нарисовать квадратная карта от Point (-100, -100) до Point (100, 100). Что бы произойдет, если вы используете тип PositivePoint? Будет ли программа поведение будет неизменным? Это не будет. Это «неизменное поведение» является единственным вещь, которую я не понимаю. Если определение подтипа был просто inheriting and overriding от другого типа было бы хорошо, но это не так дело.

Ответы [ 4 ]

3 голосов
/ 15 февраля 2010

Лисков верен, PositivePoint ≤ Point, потому что PositivePoint - это уточнение of Point. Любой код, который использует Point, также должен иметь возможность использовать PositivePoint, потому что всегда была вероятность того, что координаты Point в любом случае были положительными . Обратное неверно, потому что код, использующий PositivePoint, может действовать в предположении, что координаты всегда положительны, и замена PositivePoint на Point нарушит это предположение.

Обратите внимание, что она не говорит, что PositivePoint может заменить Point, просто что PositivePoint можно использовать там, где требуется Point.

1 голос
/ 15 февраля 2010

Идея состоит в том, что любая функция, которая принимает PositivePoint, полагается на тот факт, что значения точки являются положительными. Если вы перешли в точку, значения которой не являются положительными, предположение ложно, и функция потерпит неудачу.

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

Обратите внимание, что это верно только для неизменного класса Point. Если бы вы могли изменить значение точки, PositivePoint и Point вообще не могли бы иметь отношения подкласса, потому что операция p.x = -1 не будет выполнена для PositivePoints.

Редактировать: уточнять:

Допустим, у нас есть 2-мерный массив, который автоматически увеличивается при необходимости (то есть, при передаче двух положительных индексов вы никогда не получите ошибку индекса за пределами границ). Теперь у нас есть функция, которая принимает PositiveInteger p, а затем обращается к 2d-массиву по индексу x, y. Это не может не сработать, потому что x и y гарантированно будут положительными, а 2d-массив может быть проиндексирован любой парой положительных индексов. Однако, если Point является подтипом PositivePoint, p может иметь отрицательные значения, даже если он объявлен положительным. Это будет означать, что его уже нельзя использовать для индексации массива.

Однако функция, принимающая точку, не знает, являются ли значения точки отрицательными или положительными - она ​​уже должна учитывать вероятность того, что они положительные. Поэтому передача в PositiveInteger не может ничего сломать.

1 голос
/ 15 февраля 2010

Вы можете смоделировать отношения типа через подмножества .

PositivePoint ⊂ Point имеет место по той же причине, что и PositiveInt ⊂ Int: положительные числа являются подмножеством всех возможных чисел!

Каждый PositivePoint принадлежит Point с, но не наоборот.

0 голосов
/ 15 февраля 2010

Я не видел символа ≤, используемого для обозначения этого раньше, но то, что я думаю, означает PositivePoint ≤ Point означает, что Point имеет больший диапазон потенциальных значений, чем PositivePoint (то есть подмножество Point, все экземпляры PositivePoint могут быть заменены действительными экземплярами Point, но не наоборот.)

...