Здравствуйте, igna, Вы писали:
I>Верно ли следующее?:
I>Если классы B и D связаны отношением D Is-a B; то любое утверждение истинное для B, является истинным для D.
Насколько я понимаю, нет.
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Здравствуйте, igna, Вы писали:
I>Верно ли следующее?:
I>Если классы B и D связаны отношением D Is-a B; то любое утверждение истинное для B, является истинным для D.
Что понимается под термином класс? Это понятие, имхо, не поддается универсальной формализации, оставаясь специфичным для каждой группы языков.
Если говорить о типах, а тип в свою очередь рассматривать как множество объектов, обладающих определенными свойствами, то да. В нотации теории множеств:
B ={x | PB(x)}
D ={x | PD(x) /\ PB(x)}
Подразумевается, что x берутся из большого универсума, и PB(x), PD(x) — предикаты над элементами универсума. Чтобы D было подмножеством (subtype) B необходимо, чтобы для любого его элемента выполнялся предикат PB(x).
Здравствуйте, igna, Вы писали:
I>Здравствуйте, D. Mon, Вы писали:
DM>>http://en.wikipedia.org/wiki/Liskov_substitution_principle
I>Это да или нет?
Это ни то ни другое. Могут быть утверждения истинные для B но ложные для D но при этом LSP строго соблюдается.
Здравствуйте, igna, Вы писали:
GIV>>Это ни то ни другое. Могут быть утверждения истинные для B но ложные для D но при этом LSP строго соблюдается.
I>Спасибо, только это и есть "нет".
Нет это не есть "нет" как ответ на изначальный вопрос
Ответ "нет" тут на утверждение:
Если классы B и D связаны отношением D подкласс B и соблюдается LSP; то любое утверждение истинное для B, является истинным для D.
А это таки другой вопрос
Интуитвно понятно, что и на оригинальный вопрос ответ "нет" но формального доказательства я не могу привести
Здравствуйте, igna, Вы писали:
I>Верно ли следующее?: I>Если классы B и D связаны отношением D Is-a B; то любое утверждение истинное для B, является истинным для D.
Неверно, утверждение «x is not D» в общем случае не удовлетворяет условию.
Здравствуйте, deniok, Вы писали:
D>Здравствуйте, igna, Вы писали:
I>>Верно ли следующее?:
I>>Если классы B и D связаны отношением D Is-a B; то любое утверждение истинное для B, является истинным для D.
D>Что понимается под термином класс? Это понятие, имхо, не поддается универсальной формализации, оставаясь специфичным для каждой группы языков.
D>Если говорить о типах, а тип в свою очередь рассматривать как множество объектов, обладающих определенными свойствами, то да. В нотации теории множеств: D>
D>B ={x | PB(x)}
D>D ={x | PD(x) /\ PB(x)}
D>
D>Подразумевается, что x берутся из большого универсума, и PB(x), PD(x) — предикаты над элементами универсума. Чтобы D было подмножеством (subtype) B необходимо, чтобы для любого его элемента выполнялся предикат PB(x).
Подмножество и подтип не тождественные понятия.
Простой пример: квадрат является подмножеством прямоугольника но не являеться его подтипом.
Или например в С/С++ типы short и long.
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, igna, Вы писали:
I>>Верно ли следующее?: I>>Если классы B и D связаны отношением D Is-a B; то любое утверждение истинное для B, является истинным для D.
Кё>Неверно, утверждение «x is not D» в общем случае не удовлетворяет условию.
Ваше утверждение не удовлетворяет условию см. выделенное
Вы доказываете обратное, что B не всегда D.
Здравствуйте, matcode, Вы писали:
D>>Если говорить о типах, а тип в свою очередь рассматривать как множество объектов, обладающих определенными свойствами, то да. В нотации теории множеств: D>>
D>>B ={x | PB(x)}
D>>D ={x | PD(x) /\ PB(x)}
D>>
D>>Подразумевается, что x берутся из большого универсума, и PB(x), PD(x) — предикаты над элементами универсума. Чтобы D было подмножеством (subtype) B необходимо, чтобы для любого его элемента выполнялся предикат PB(x).
M>Подмножество и подтип не тождественные понятия. M>Простой пример: квадрат является подмножеством прямоугольника но не являеться его подтипом. M>Или например в С/С++ типы short и long.
Запиши определения того, что есть квадрат и что есть прямоугольник, на языке множеств c выделением по предикатам
Здравствуйте, igna, Вы писали:
I>Верно ли следующее?:
I>Если классы B и D связаны отношением D Is-a B; то любое утверждение истинное для B, является истинным для D.
Неверно. Во всяком случае для C++
Доказательство:
Дано:
struct B { ... };
struct D: B { ... };
D d;
B& b = d;
if (b.predicate())
assert(d.predicate()); // 1
Надо определить такой predicate, что бы утверждение (1) было ложно.
Легко:
struct B {
bool predicate() { return true;}
};
struct D: B {
bool predicate() { return false;}
};
Здравствуйте, matcode, Вы писали:
M>Ваше утверждение не удовлетворяет условию см. выделенное
Верно ли, что «любое утверждение истинное для B, является истинным для D»
Моё утверждение: x is not D.
B is not D = true when B != D
D is not D = false
=> не любое
При этом наличие или отсутствие связи Is-a не играет никакой роли, потому что само условие логически противоречиво. Нет таких различимых объектов (в философском смысле — любой объект) B и D, чтобы для них выполнилось это условие, это нарушает философский принцип A=A.
Здравствуйте, igna, Вы писали:
I>Верно ли следующее?: I>Если классы B и D связаны отношением D Is-a B; то любое утверждение истинное для B, является истинным для D.
Если утверждение является инвариантом B, то верно.
Если утверждение является предусловием B, то верно (для подтипов требуется контрвариантность предусловий).
Если утверждение является постусловием B, то верно (для подтипов требуется ковариантность постусловий).
В ином случае, вообще говоря, неверно.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, matcode, Вы писали:
M>>Неверно. Во всяком случае для C++
I>В твоем примере D и B не связаны отношением IsA.
Вообщем-то ты прав.
Мой пример скорее доказывает, что в C++ наследование не всегда являеться отношением "Is-a", другими словами наследник может быть не подтипом родителя и как следствие объект можно привести к типу не являющемуся его супертипом, что IMHO есть нарушение принципов ООП или по меньшей мере LSP уж точно.
Ну хорошо, не будем трогать наследование, собственно отношением "Is-a" даже в C++ можно выразить не только наследованием.
Тогда если немного дополнить оригинальное условие то оно будет почти соответствовать LSP.
А именно: "любое утверждение в терминах B,истинное для B, является истинным для D"
В это случае,например, "x is not D"
не катит, так это явно не терм из B.
Почему же почти, а не точно соответствовать LSP(Даже если не касться точности формулировки)?
Потому что LSP определяет, что при этом условии D будет подтипом B. Он не определяет, что только при этом условии, т.е. условие достаточное, но не необходимое. Поэтому сторого говоря обратное утверждение может быть не всегда верно.
Вывод:
без дополнениея — неверно
c дополнением — скорее верно, хотя зависит от точного определения, что такое "подтип"
Здравствуйте, deniok, Вы писали:
D>Здравствуйте, matcode, Вы писали:
D>>>Если говорить о типах, а тип в свою очередь рассматривать как множество объектов, обладающих определенными свойствами, то да. В нотации теории множеств: D>>>
D>>>Подразумевается, что x берутся из большого универсума, и PB(x), PD(x) — предикаты над элементами универсума. Чтобы D было подмножеством (subtype) B необходимо, чтобы для любого его элемента выполнялся предикат PB(x).
M>>Подмножество и подтип не тождественные понятия. M>>Простой пример: квадрат является подмножеством прямоугольника но не являеться его подтипом. M>>Или например в С/С++ типы short и long.
D>Запиши определения того, что есть квадрат и что есть прямоугольник, на языке множеств c выделением по предикатам
Ну хорошо,
Множество прямоугольников можно определить так:
"Все x, принадалежащее множеству четырехугольников(что такое четырехугольник определять не буду) и имеющее прямые углы"
Множество квадратов так:
"Все x, принадалежащее множеству прямоугольников и имеющее равные стороны"
Только зачем это? Я просто указал что подмножество и подтип это не одно и то же.
Или ты не согласен?
Здравствуйте, matcode, Вы писали:
M>А именно: "любое утверждение в терминах B,истинное для B, является истинным для D" M>В это случае,например, "x is not D"
x.className == "B" — исключительно в терминах B, где Object.className — метод, возвращающий конечный уникальный тип объекта, или гуид, необходимый например, для сериализации.
Здравствуйте, matcode, Вы писали:
M>Здравствуйте, deniok, Вы писали:
D>>Запиши определения того, что есть квадрат и что есть прямоугольник, на языке множеств c выделением по предикатам
M>Ну хорошо, M>Множество прямоугольников можно определить так:
M>"Все x, принадалежащее множеству четырехугольников(что такое четырехугольник определять не буду) и имеющее прямые углы"
M>Множество квадратов так:
M>"Все x, принадалежащее множеству прямоугольников и имеющее равные стороны"
M>Только зачем это? Я просто указал что подмножество и подтип это не одно и то же. M>Или ты не согласен?
При том подходе, рамки которого я задал, определив тип как множество, — одно и то же.
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, matcode, Вы писали:
M>>А именно: "любое утверждение в терминах B,истинное для B, является истинным для D" M>>В это случае,например, "x is not D"
не катит, так это явно не терм из B.
Кё>x.className == "B" — исключительно в терминах B, где Object.className — метод, возвращающий конечный уникальный тип объекта, или гуид, необходимый например, для сериализации.
Если найдеться такой y из D, для которого y.className == "B" ложно то D не будет подтипом B( точнее если это свойсто будет влиять на поведение программы), это следует из определения LSP. Кстати это пример разбираеться первым в статье по LSP.
Но я же говорю, что все зависит от определения подтипа. Из википедии
the supertype-subtype relation is often taken to be the one defined by the Liskov substitution principle; however, any given programming language may define its own notion of subtyping, or none at all.
Т.е. если мы определим "подтип" через LSP, то в твоем случае D это не подтип B. Если как-то по другому то вполне может.
Между прочем не так просто найти такие типы в рельном мире, которые буду имет отношение "Is-a" в соответствий с LSP.
Зачастую они могут удовлетворять этому отношению, только при определенных допущениях или при определенном использованиие(например когда не используться метаинформация).
Здравствуйте, matcode, Вы писали:
M>Т.е. если мы определим "подтип" через LSP, то в твоем случае D это не подтип B. Если как-то по другому то вполне может.
Если мы определим подтип через LSP, то подтипов не существует вообще. Считая, что B и D разные, если «B можно отличить от D», то утверждение q(x) = «(тип) x можно отличить от B» в общем случае доказывает, что LSP не выполняется при разных B и D никогда.
Здравствуйте, Кодёнок, Вы писали:
Кё>Здравствуйте, matcode, Вы писали:
M>>А именно: "любое утверждение в терминах B,истинное для B, является истинным для D" M>>В это случае,например, "x is not D"
не катит, так это явно не терм из B.
Кё>x.className == "B" — исключительно в терминах B, где Object.className — метод, возвращающий конечный уникальный тип объекта, или гуид, необходимый например, для сериализации.
К сожалению, это утверждение не является универсально справедливым для всех экземпляров B.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
Кё>>x.className == "B" — исключительно в терминах B, где Object.className — метод, возвращающий конечный уникальный тип объекта, или гуид, необходимый например, для сериализации. S>К сожалению, это утверждение не является универсально справедливым для всех экземпляров B.
Здравствуйте, Кодёнок, Вы писали:
Кё>x.className == "B" — исключительно в терминах B, где Object.className — метод, возвращающий конечный уникальный тип объекта, или гуид, необходимый например, для сериализации.
Это утверждение не в терминах B и, вообще не в терминах классов. Это — утверждение метауровня.
Здравствуйте, Трурль, Вы писали:
Кё>>x.className == "B" — исключительно в терминах B, где Object.className — метод, возвращающий конечный уникальный тип объекта, или гуид, необходимый например, для сериализации.
Т>Это утверждение не в терминах B и, вообще не в терминах классов. Это — утверждение метауровня.
Что-то я тогда не очень понимаю ваше ООП. Дай пример утверждений в терминах классов?
Здравствуйте, Кодёнок, Вы писали:
Кё>Это как?
А так, что те экземпляры, точный тип которых входит в тип B, но не является им, не будут возвращать "B". Всего делов-то.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
Кё>>Это как? S>А так, что те экземпляры, точный тип которых входит в тип B, но не является им, не будут возвращать "B". Всего делов-то.
Так именно для этого я его и придумал. Чтобы для типа и подтипов могли возвращаться разные значения. Это показывает, что LSP не может выполняться для абсолютно любого утверждения.
Здравствуйте, Кодёнок, Вы писали: Кё>Так именно для этого я его и придумал. Чтобы для типа и подтипов могли возвращаться разные значения. Это показывает, что LSP не может выполняться для абсолютно любого утверждения.
LSP и не собиралось выполняться для вааще любого утверждения. Вот представь себе, что у тебя есть B и C, причем C — уже подтип B. Если мы добавляем D и хотим узнать, является ли он подтипом B, то в D можно проверять только утверждения, справедливые для экземпляров как B, так и C.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
Кё>>Так именно для этого я его и придумал. Чтобы для типа и подтипов могли возвращаться разные значения. Это показывает, что LSP не может выполняться для абсолютно любого утверждения. S>LSP и не собиралось выполняться для вааще любого утверждения. Вот представь себе, что у тебя есть B и C, причем C — уже подтип B. Если мы добавляем D и хотим узнать, является ли он подтипом B, то в D можно проверять только утверждения, справедливые для экземпляров как B, так и C.
Типа x.className != "D", которое справедливо как для B, так и для C?