Принцип замещения Лисков гласит:
Инварианты супертипа должны сохраняться в подтипе.
Меня особенно интересует пересечение этого принципа и полиморфизма. В частности, полиморфизм подтипов, хотя на самом деле это похоже на параметрический полиморфизм и классы типов Haskell.
Итак, я знаю, что функции являются подтипами, когда их аргументы контравариантны, а типы возвращаемых значений ковариантны. Мы можем предположить, что методы — это просто функции с неявным аргументом «я». Однако это, по-видимому, означает, что если подкласс переопределяет метод родителя, он больше не является подтипом, поскольку один из его методов больше не является подтипом.
Например. Возьмите следующий псевдокод:
class Parent:
count : int
increment : Parent -> ()
{
count += 1
}
class Child inherits Parent:
increment : Child -> ()
{
count += 2
}
Итак, возвращаясь к LSP: можем ли мы сказать, что свойство Parent.increment()
должно сохраняться для Child.increment()
, даже если эти два не подчиняются строгому отношению подтипа?
В более общем плане мой вопрос таков: как правила подтипирования взаимодействуют с более конкретными аргументами полиморфных функций и как правильно думать об этих двух концепциях вместе?