Вокруг Liskov Substitution Principle
Jul. 8th, 2007 03:49 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
LSP гласит:
Пусть q(t) некоторое свойство, выполняющееся для всех t типа T. Тогда, если S подтип T, то q(s) должно выполняться для всех s типа S.
Смысл в том, что при выполнении LSP мы можем подставлять (substitute) объект типа S вместо объекта типа T, при этом никакие свойства программы не будут нарушены, то есть программа останется корректной.
Что здесь понимается под свойствами? ИМХО, исключительно инварианты публичного интерфейса. То есть что-то типа
Для любых t типа StackOfX и x типа X последовательность операций
t.push(x);
t.pop();
возвращает t в исходное состояние.
А вот sizeof(T)=16 – это не свойство в том смысле, в котором оно вводится в LSP. Оно апеллирует к внешним по отношению к публичному интерфейсу вещам. То есть sizeof(S) может быть равно 24. Это к LSP не относится. Тут, вроде, говорят, что sizeof ковариантна по возвращаемому значению.
Свойства в LSP-ном смысле на традиционных ООП языках не задаются, а подразумеваются, синтаксиса не хватает. А в Хаскелле (GHC) они могут использоваться для оптимизаций, через rewrite rules
{-# RULES
"myRule" forall t x. pop (push t x) = t
#-}
И кто теперь более ООП? :-)
ЗЫ: Вроде нигде не наврал.
ЗЫ: Вроде нигде не наврал.
no subject
Date: 2007-07-08 04:42 pm (UTC)Но в целом идея хороша. А то у меня были проблемы с этим "принципом".
no subject
Date: 2007-07-08 05:14 pm (UTC)Вот в том-то и дело, что частью интерфейса - вроде как не может. То есть, что такое 16 - в этой науке неведомо. Поинт в том, что для всех параметров функций интерфейса мы должны выставить квантор общности и написать некоторый закон, который для этого интерфейса (и только для него!) выполняется. То есть скажем для
interface INum {
INum INum::plus(INum a);
INum INum::minus(INum a);
}
есть закон
forall x y : x.plus(y).minus(y) == x
Нельзя при формулировании закона подразумевать существование чего-то кроме самого этого интерфейса. (Ну может быть какие-то другие интерфейсы - в эту сторону не думал).
Хотя возможно это мои домыслы. Посмотрим, что умные люди скажут.
no subject
Date: 2007-07-09 07:27 am (UTC)Похоже, что я погорячился насчёт
> То есть, что такое 16 - в этой науке неведомо
Тем не менее, если в T объявлено в качестве инварианта, что
forall t : t.someMethod() == 16
то в субтипе S этот инвариант тоже должен сохраняться s.someMethod() должен быть равен 16 и ничему другому.
no subject
Date: 2007-07-09 07:14 am (UTC)"myRule" forall t x. pop (push t x) = t
#-}
Ого! А ведь у меня была похожая идея для оптимизатора. Опередели! :)
no subject
Date: 2007-07-09 07:31 am (UTC)Могу дать полную и неограниченную лицензию :))
Копирайт можешь не писать (тем более, как я подозреваю, он не мой - слишком уж напрашивающаяся мысль)