Введите - отношение Подтипа. Что-то кажется неясным

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

Barbara Liskov, “Абстракция данных и иерархия”, SIGPLAN замечает, 23,5 (май 1988):

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

Затем это идет с примером:

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

Мы можем сказать ту Точку PositivePoint ≤?

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

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

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


Править

Только для создания вещей легче вопрос: можно ли сказать это PositivePoint подтип Point? Почему?


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

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

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

6
задан sepp2k 5 September 2010 в 12:57
поделиться

4 ответа

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

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

3
ответ дан 17 December 2019 в 04:46
поделиться

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

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

Каждая PositivePoint принадлежит Point s, но не наоборот.

1
ответ дан 17 December 2019 в 04:46
поделиться

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

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

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

Edit: To elaborate:

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

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

1
ответ дан 17 December 2019 в 04:46
поделиться

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

0
ответ дан 17 December 2019 в 04:46
поделиться