Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
Не знаю можно ли здесь q(x) заменить на q(x1, x2), но если можно, и в случае соблюдения LSP верно следуюшее:
Let q(x1, x2) be a property provable about objects x1 and x2 of type T. Then q(y1, y2) should be true for objects y1 and y2 of type S where S is a subtype of T.
, то в .NET наследование System.String от System.Object нарушает LSP, потому как
Object.ReferenceEquals(x1, x2) || !x1.Equals(x2)
всегда верно для x1 и x2 являюшихся Object, но
Object.ReferenceEquals(y1, y2) || !y1.Equals(y2)
не верно в общем случае для y1 и y2 являющихся String.
Вы бы попробовали понять об чём этот LSP, а не подходить к нему формально, да ещё с произвольными изменениями.
В таком формальном подходе LSP вообще невозможен, так как при наследовании как минимум меняется класс объекта, даже если ничего не добавлено и не переопределено.
Понятно? А теперь думайте, что же на самом деле означает LSP.
Здравствуйте, igna, Вы писали:
I>не верно в общем случае для y1 и y2 являющихся String.
А я всегда говорил: такое наследование — фтопку.
Рулят полиморфные типы (ака генерики), интерфейсы, ну и в крайнем случае наследование от абстрактных классов.
Здравствуйте, igna, Вы писали:
I>В Википедии дано такое определение LSP:
I>
I>Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
[skiped]
Это всё не то.
Смысл в том, что любые семантические контракты T, используемые при написания полиморфного кода, использующего T, должны при наследовании сохраняться.
class My
{
protected:
int data;
...
public:
virtual void Reset(); // Декларировано, что Reset выставляет data в 0. (Задан семантический контракт)
...
}
// полиморфная функцияvoid doSomething (My& my)
{
...
my.Reset();
... // код, полагающийся на семантический контракт data == 0
}
Любой наследник My при перегрузке Reset() должен поддерживать семантический контракт (выставлять data в ноль), иначе поведение doSomething будет неверным
class MyChild : public My
{
virtual void Reset(){data = 1;} // Опс! При перегрузке нарушили контракт.
}
void foo()
{
MyChild x;
doSomething(x); // Бац! Прострелили ногу...
}
Здравствуйте, igna, Вы писали:
I>В Википедии дано такое определение LSP:
I>
I>Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
Вы немного неправильно перевели фразу. "Should be true" в данном случае означает "должно быть правильным (осмысленным)" а не "должно возвращать true".
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>В Википедии дано такое определение LSP:
I>
I>Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
I>Не знаю можно ли здесь q(x) заменить на q(x1, x2), но если можно, и в случае соблюдения LSP верно следуюшее:
I>
I>Let q(x1, x2) be a property provable about objects x1 and x2 of type T. Then q(y1, y2) should be true for objects y1 and y2 of type S where S is a subtype of T.
I>, то в .NET наследование System.String от System.Object нарушает LSP, потому как
I>
Здравствуйте, igna, Вы писали:
I>В Википедии дано такое определение LSP:
I>
I>Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
I>Не знаю можно ли здесь q(x) заменить на q(x1, x2), но если можно, и в случае соблюдения LSP верно следуюшее:
I>
I>Let q(x1, x2) be a property provable about objects x1 and x2 of type T. Then q(y1, y2) should be true for objects y1 and y2 of type S where S is a subtype of T.
I>, то в .NET наследование System.String от System.Object нарушает LSP, потому как
I>
I>не верно в общем случае для y1 и y2 являющихся String.
И что из этого следует?
И почему только string? Любой класс в котором перегружено Equals его тоже нпрушает, иначе небыло бы смысла его перегружать.
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, igna, Вы писали:
I>>не верно в общем случае для y1 и y2 являющихся String.
N>А я всегда говорил: такое наследование — фтопку.
А какое наследование не фтопку, кроме ниже описанных
N>Рулят полиморфные типы (ака генерики), интерфейсы, ну и в крайнем случае наследование от абстрактных классов.
Здравствуйте, igna, Вы писали: I>не верно в общем случае для y1 и y2 являющихся String.
Это также неверно в общем случае для y1 и y2, являющихся object. Поскольку вначале была сделана неверная посылка (предложенное свойство не является доказуемым), то и вывод неверен.
Конкретно, ваша ошибка в том, что вы сузили тип T до точного object, выбросив из рассмотрения его подтипы. А этого делать нельзя. Все объекты, которые отвечают true на x is T, входят в этот тип. В частном случае System.Object реализацим Equals и ReferenceEquals совпадают. Но это не является частью контракта.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
mkizub wrote:
> Да не пример брать надо. Думать надо. > > obj.GetType() > уже нарушается при *любом* наследовании. Это что, значит ОО не > соответствует LSP?
Может поэтому в некоторых языках используют более концептуально чистое typeof(obj)?
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ., Вы писали:
>> obj.GetType() >> уже нарушается при *любом* наследовании. Это что, значит ОО не соответствует LSP? .>Может поэтому в некоторых языках используют более концептуально чистое typeof(obj)?
А в чём разница? Принцип "нарушается" всё так же успешно.
Трурль wrote:
> .>Может поэтому в некоторых языках используют более концептуально чистое > typeof(obj)? > Концептуально чистое — это obj is T.
Ну это булева функция... и если тип является классом... есть рефлексия... скажем для такой записи:
Type t = typeof(obj)
но да... уже не чисто.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Т>>Нет, это значит что obj.GetType() не соответсвует ОО.
M>Это у вас какая-то неизвестная науке ревизия OO, из которой начисто отрезали полиморфизм.
.GetType — это не полиморфизм, а концептуально ему противоположная RTTI, а программирование с явным использованием RTTI действительно не соответствует ОО.
Это расширение ОО, в достаточно произвольную сторону.
D>Смысл в том, что любые семантические контракты T, используемые при написания полиморфного кода, использующего T, должны при наследовании сохраняться.
И они тоже в приведенном примере не сохраняются. Object.Equals есть расширительно истолкованный Object.ReferenceEquals, а String.Equals не имеет никакого отношения к String.ReferenceEquals.
Как раз именно семантический контракт у Equals и не сохранен.