История изменений
Исправление den73, (текущая версия) :
ты знаешь этот контракт.
Его нельзя «знать». Это вопрос соглашения, я тебе предложил два варианта. А ты вместо того, чтобы начать разговор о том, что считать контрактом, пытаешься вывести меня на признание ошибки.
Да, если тебе это надо - я ошибся в том, что поверил Википедии. Её не надо было читать. И я говорил не о ненужности, а о парадоксальности (некорректности), которая есть в Википедии, но которой нет в первоисточнике. Конечно, парадоксальный принцип не нужен.
Ладно, он не парадоксален. Вопрос нужности остаётся. С одной стороны, вроде всё круто.
Но у меня получается, что если виртуальная функция является частью контракта, то она должна быть в базовом классе абстрактной (и на самом деле быть исключена из контракта) и по любой цепочке наследования должна переопределяться не более одного раза. Здесь получается иной парадокс: «опа есть, а слова нет». Т.е. мы заводим виртуальную функцию (скажем, draw) для полиморфизма, но контракта нет и пользоваться в базовом классе, не нарушив принцип Лисков, ей как бы нельзя. Но в реальности, именно этой вирт.ф-ей и надо пользоваться, и именно для базового класса всех виджетов, чтобы фактически нарисовать какой-нибудь грид виджетов.
В Qt я полез в примера подобной конструкции, но за 10 минут ничего лучше, чем QWidget::heightForWidth не нашёл. Думаю, принцип Лисков всё же тут нарушается, потому что нужно было бы написать «не вызывайте heightForWidght для QWidget». И естественно, компилятор бы не мог это проверить, что противоречит практичности.
Данного примера недостаточно, чтобы понять, применяется ли в Qt принцип Лисков. Мне всегда казалось, что в библиотеке виджетов есть базовый виртуальный Draw, который ничего не делает, и он несколько раз перегружается по иерархии. Т.е. никаким принципом Лисков и не пахнет. Как раз наоборот, виртуальность используется для того, чтобы рисовать разные виджеты по-разному, не зная конкретного типа виджета. Конечно, можно организовать это и по-другому. Но что-то мне сдаётся, что очень часто конкретный виджет рисуется не так, как его предок, который зачастую тоже может рисоваться.
Ладно, спасибо за беседу. Нужно будет потом ещё помедитировать над этим принципом. Он хорош тем, что определяет вменяемое понятие «подтипа» и в принципе позволяет частично обобщить понятие «подтипа» с базовых типов на объекты. Но вообще говоря, наследник в смысле ООП не является подтипом. И для разработки языка остаётся вопрос, как работать с «наследником в смысле ООП», как его назвать и нужно ли вообще такое понятие, как «наследник в смысле ООП».
Исправление den73, :
ты знаешь этот контракт.
Его нельзя «знать». Это вопрос соглашения, я тебе предложил два варианта. А ты вместо того, чтобы начать разговор о том, что считать контрактом, пытаешься вывести меня на признание ошибки.
Да, если тебе это надо - я ошибся в том, что поверил Википедии. Её не надо было читать. И я говорил не о ненужности, а о парадоксальности (некорректности), которая есть в Википедии, но которой нет в первоисточнике. Конечно, парадоксальный принцип не нужен.
Ладно, он не парадоксален. Вопрос нужности остаётся. С одной стороны, вроде всё круто.
Но у меня получается, что если виртуальная функция является частью контракта, то она должна быть в базовом классе абстрактной (и на самом деле быть исключена из контракта) и по любой цепочке наследования должна переопределяться не более одного раза. Здесь получается иной парадокс: «опа есть, а слова нет». Т.е. мы заводим виртуальную функцию (скажем, draw) для полиморфизма, но контракта нет и пользоваться в базовом классе, не нарушив принцип Лисков, ей как бы нельзя. Но в реальности, именно этой вирт.ф-ей и надо пользоваться, и именно для базового класса всех виджетов, чтобы фактически нарисовать какой-нибудь грид виджетов.
В Qt я полез в примера подобной конструкции, но за 10 минут ничего лучше, чем QWidget::heightForWidth не нашёл. Думаю, принцип Лисков всё же тут нарушается, потому что нужно было бы написать «не вызывайте heightForWidght для QWidget». И естественно, компилятор бы не мог это проверить, что противоречит практичности.
Данного примера недостаточно, чтобы понять, применяется ли в Qt принцип Лисков. Мне всегда казалось, что в библиотеке виджетов есть базовый виртуальный Draw, который ничего не делает, и он несколько раз перегружается по иерархии. Т.е. никаким принципом Лисков и не пахнет. Как раз наоборот, виртуальность используется для того, чтобы рисовать разные виджеты по-разному, не зная конкретного типа виджета. Конечно, можно организовать это и по-другому. Но что-то мне сдаётся, что очень часто конкретный виджет рисуется не так, как его предок, который зачастую тоже может рисоваться.
Ладно, спасибо за беседу. Нужно будет потом ещё помедитировать над этим принципом. Он хорош тем, что определяет вменяемое понятие «подтипа». Наследник в смысле ООП не является подтипом. Но дыра всё равно остаётся - как надо правильно называть «наследника в смысле ООП», кроме как «грязным хаком из С++»? Подтипом он (вообще говоря) точно не является.
Исходная версия den73, :
ты знаешь этот контракт.
Его нельзя «знать». Это вопрос соглашения, я тебе предложил два варианта. А ты вместо того, чтобы начать разговор о том, что считать контрактом, пытаешься вывести меня на признание ошибки.
Да, если тебе это надо - я ошибся в том, что поверил Википедии. Её не надо было читать. И я говорил не о ненужности, а о парадоксальности (некорректности), которая есть в Википедии, но которой нет в первоисточнике. Так что вопрос о парадоксальности можно закрывать.
Остаётся вопрос о нужности. У меня получается, что если виртуальная функция является частью контракта, то она должна быть в базовом классе абстрактной (и на самом деле быть исключена из контракта) и по любой цепочке наследования должна переопределяться не более одного раза. Здесь получается иной парадокс: «опа есть, а слова нет». Т.е. мы заводим виртуальную функцию (скажем, draw) для полиморфизма, но контракта нет и пользоваться в базовом классе, не нарушив принцип Лисков, ей как бы нельзя. Но в реальности, именно этой вирт.ф-ей и надо пользоваться, и именно для базового класса всех виджетов, чтобы фактически нарисовать какой-нибудь грид виджетов.
В Qt я полез в примера подобной конструкции, но за 10 минут ничего лучше, чем QWidget::heightForWidth не нашёл. Думаю, принцип Лисков всё же тут нарушается, потому что нужно было бы написать «не вызывайте heightForWidght для QWidget». И естественно, компилятор бы не мог это проверить, что противоречит практичности.
Данного примера недостаточно, чтобы понять, применяется ли в Qt принцип Лисков. Мне всегда казалось, что в библиотеке виджетов есть базовый виртуальный Draw, который ничего не делает, и он несколько раз перегружается по иерархии. Т.е. никаким принципом Лисков и не пахнет. Как раз наоборот, виртуальность используется для того, чтобы рисовать разные виджеты по-разному, не зная конкретного типа виджета. Конечно, можно организовать это и по-другому. Но что-то мне сдаётся, что очень часто конкретный виджет рисуется не так, как его предок, который зачастую тоже может рисоваться.
Ладно, спасибо за беседу. Нужно будет потом ещё помедитировать над этим принципом. Он хорош тем, что определяет вменяемое понятие «подтипа». Наследник в смысле ООП не является подтипом. Но дыра всё равно остаётся - как надо правильно называть «наследника в смысле ООП», кроме как «грязным хаком из С++»? Подтипом он (вообще говоря) точно не является.