Тут как-то пару месяцев обсуждали этот метод у Object из .Net в рамках наследования. Нашёл интересную статью по этому поводу (правда там Ява, но ничего это не меняет). Там высказывается вполне корректная на мой взгляд точка зрения: equals не должен быть методом объекта, иначе он будет не симметричным, что ведёт к логическим ошибкам.
Здравствуйте, Курилка, Вы писали:
К>Тут как-то пару месяцев обсуждали этот метод у Object из .Net в рамках наследования. Нашёл интересную статью по этому поводу (правда там Ява, но ничего это не меняет). Там высказывается вполне корректная на мой взгляд точка зрения: equals не должен быть методом объекта, иначе он будет не симметричным, что ведёт к логическим ошибкам.
Здравствуйте, ZevS, Вы писали:
ZS>Здравствуйте, Курилка, Вы писали:
К>>Тут как-то пару месяцев обсуждали этот метод у Object из .Net в рамках наследования. Нашёл интересную статью по этому поводу (правда там Ява, но ничего это не меняет). Там высказывается вполне корректная на мой взгляд точка зрения: equals не должен быть методом объекта, иначе он будет не симметричным, что ведёт к логическим ошибкам.
ZS>Ну не зря же этот метод виртуальный?
Если подходить с т.зр. логики — зря.
Практически в угоду ООП извратили суть отношения равенства, а ёжики "плевались, но лезли на кактус"
Правда с практической т.зр. проблема не такая уж страшная.
...
ZS>>Ну не зря же этот метод виртуальный?
К>Если подходить с т.зр. логики — зря. К>Практически в угоду ООП извратили суть отношения равенства, а ёжики "плевались, но лезли на кактус" К>Правда с практической т.зр. проблема не такая уж страшная.
Использование классовых методов, реализованных через экземплярные спасет мир.
class Object
...
public static bool Equals(object objA, object objB)
{
if (objA == objB)
{
return true;
}
if ((objA != null) && (objB != null))
{
return objA.Equals(objB);
}
return false;
}
Здравствуйте, ZevS, Вы писали:
ZS>Здравствуйте, Курилка, Вы писали:
ZS>...
ZS>>>Ну не зря же этот метод виртуальный?
К>>Если подходить с т.зр. логики — зря. К>>Практически в угоду ООП извратили суть отношения равенства, а ёжики "плевались, но лезли на кактус" К>>Правда с практической т.зр. проблема не такая уж страшная.
ZS>Использование классовых методов, реализованных через экземплярные спасет мир.
Классовые — это статические типа чтоль?
Чем твоя схема отличается от objA.equals(objB), которая несимметрична?
Доп. проверки на равенство экземпляров и null роли тут не играют
..
ZS>>Использование классовых методов, реализованных через экземплярные спасет мир.
К>Классовые — это статические типа чтоль? К>Чем твоя схема отличается от objA.equals(objB), которая несимметрична? К>Доп. проверки на равенство экземпляров и null роли тут не играют
Ну, я обычно сравниваю объекты на равенство статическим методом базового класса. И мне не важен тип объекта, часто я его и не знаю. По-моему, удобно. Пусть и извращение.
Здравствуйте, ZevS, Вы писали:
ZS>Здравствуйте, Курилка, Вы писали:
ZS>..
ZS>>>Использование классовых методов, реализованных через экземплярные спасет мир.
К>>Классовые — это статические типа чтоль? К>>Чем твоя схема отличается от objA.equals(objB), которая несимметрична? К>>Доп. проверки на равенство экземпляров и null роли тут не играют
ZS>Ну, я обычно сравниваю объекты на равенство статическим методом базового класса. И мне не важен тип объекта, часто я его и не знаю. По-моему, удобно. Пусть и извращение.
Ну почему извращение, это как раз по сути логически более правильный способ.
Просто проблема с перегрузкой оператора, которая-то и делает его несимметричным. Если же один метод в базовом классе, который ещё и final, то это почти идентично выносу его из класса.
..
ZS>>Ну, я обычно сравниваю объекты на равенство статическим методом базового класса. И мне не важен тип объекта, часто я его и не знаю. По-моему, удобно. Пусть и извращение.
К>Ну почему извращение, это как раз по сути логически более правильный способ.
Вот и получается, что виртуальный метод Equal необходим.
К>Просто проблема с перегрузкой оператора, которая-то и делает его несимметричным. Если же один метод в базовом классе, который ещё и final, то это почти идентично выносу его из класса.
Здравствуйте, ZevS, Вы писали:
ZS>Здравствуйте, Курилка, Вы писали:
ZS>..
ZS>>>Ну, я обычно сравниваю объекты на равенство статическим методом базового класса. И мне не важен тип объекта, часто я его и не знаю. По-моему, удобно. Пусть и извращение.
К>>Ну почему извращение, это как раз по сути логически более правильный способ.
ZS>Вот и получается, что виртуальный метод Equal необходим.
Откуда получается-то?
Проблема в том, что это в базовый класс запёхано, поэтому приходиться находить обходные пути.
Скажи, зачем тебе реально тут виртуальность нужна?
ObjectA.Equals(a,b) даже визуально гораздо "чище", чем a.equals(b)
Здравствуйте, Курилка, Вы писали:
К>Здравствуйте, ZevS, Вы писали:
ZS>>Здравствуйте, Курилка, Вы писали:
ZS>>..
ZS>>>>Ну, я обычно сравниваю объекты на равенство статическим методом базового класса. И мне не важен тип объекта, часто я его и не знаю. По-моему, удобно. Пусть и извращение.
К>>>Ну почему извращение, это как раз по сути логически более правильный способ.
ZS>>Вот и получается, что виртуальный метод Equal необходим.
К>Откуда получается-то? К>Проблема в том, что это в базовый класс запёхано, поэтому приходиться находить обходные пути. К>Скажи, зачем тебе реально тут виртуальность нужна? К>ObjectA.Equals(a,b) даже визуально гораздо "чище", чем a.equals(b)
А если a и b на самом деле являются экземплярами наследника ObjectA?
Здравствуйте, ZevS, Вы писали:
ZS>Здравствуйте, Курилка, Вы писали:
К>>Проблема в том, что это в базовый класс запёхано, поэтому приходиться находить обходные пути. К>>Скажи, зачем тебе реально тут виртуальность нужна? К>>ObjectA.Equals(a,b) даже визуально гораздо "чище", чем a.equals(b)
ZS>А если a и b на самом деле являются экземплярами наследника ObjectA?
Если
Ну а даже и если, и если один ObjectA1, другой ObjectA2, плюс в обоих метод переопределён, получаем веселуху
Здравствуйте, Курилка, Вы писали:
К>Здравствуйте, ZevS, Вы писали:
ZS>>Здравствуйте, Курилка, Вы писали:
К>>>Проблема в том, что это в базовый класс запёхано, поэтому приходиться находить обходные пути. К>>>Скажи, зачем тебе реально тут виртуальность нужна? К>>>ObjectA.Equals(a,b) даже визуально гораздо "чище", чем a.equals(b)
ZS>>А если a и b на самом деле являются экземплярами наследника ObjectA?
К>Если К>Ну а даже и если, и если один ObjectA1, другой ObjectA2, плюс в обоих метод переопределён, получаем веселуху
Ну это — по желанию. Можно и статический метод идиотски закодировать.
Здравствуйте, ZevS, Вы писали:
ZS>Здравствуйте, Курилка, Вы писали:
К>>Здравствуйте, ZevS, Вы писали:
ZS>>>Здравствуйте, Курилка, Вы писали:
К>>>>Проблема в том, что это в базовый класс запёхано, поэтому приходиться находить обходные пути. К>>>>Скажи, зачем тебе реально тут виртуальность нужна? К>>>>ObjectA.Equals(a,b) даже визуально гораздо "чище", чем a.equals(b)
ZS>>>А если a и b на самом деле являются экземплярами наследника ObjectA?
К>>Если К>>Ну а даже и если, и если один ObjectA1, другой ObjectA2, плюс в обоих метод переопределён, получаем веселуху
ZS>Ну это — по желанию. Можно и статический метод идиотски закодировать.
Ну ты серьёзно чтоль не улавливаешь разницу? Или тебе надо рассказывать, что статический определён на этапе компиляции, а виртуальный нет?
...
ZS>>Ну это — по желанию. Можно и статический метод идиотски закодировать.
К>Ну ты серьёзно чтоль не улавливаешь разницу? Или тебе надо рассказывать, что статический определён на этапе компиляции, а виртуальный нет?
А собственно Equal то тут при чем?
То что виртульные мотоды определяются через vtm — фича.
Здравствуйте, Курилка, Вы писали:
К>Тут как-то пару месяцев обсуждали этот метод у Object из .Net в рамках наследования...
Кое-что по теме здесь и здесь.
Здравствуйте, ZevS, Вы писали:
ZS>Здравствуйте, Курилка, Вы писали:
ZS>...
ZS>>>Ну это — по желанию. Можно и статический метод идиотски закодировать.
К>>Ну ты серьёзно чтоль не улавливаешь разницу? Или тебе надо рассказывать, что статический определён на этапе компиляции, а виртуальный нет?
ZS>А собственно Equal то тут при чем?
блин, я думал ты поймёшь, что он статический ZS>То что виртульные мотоды определяются через vtm — фича.
попробуй понять статью, надоело уже повторять, если честно
Здравствуйте, lxa, Вы писали:
lxa>Здравствуйте, Курилка, Вы писали:
К>>Тут как-то пару месяцев обсуждали этот метод у Object из .Net в рамках наследования... lxa>Кое-что по теме здесь и здесь.
Сильно не вчитывался, как говорят "много букав"
Только вот всё это похоже на шаманские танцы вокруг грабель.
Вынос в статический метод сделал бы ситуацию много понятней и проще.
Здравствуйте, Курилка, Вы писали:
К>Тут как-то пару месяцев обсуждали этот метод у Object из .Net в рамках наследования. Нашёл интересную статью по этому поводу (правда там Ява, но ничего это не меняет). Там высказывается вполне корректная на мой взгляд точка зрения: equals не должен быть методом объекта, иначе он будет не симметричным, что ведёт к логическим ошибкам.
Откуда логическая ошибка? Методы вызываются у целевого объекта, соотв. он служит образцом, запутаться невозможно. Понятное дело, что сравнение может быть нессиметричным, если аргумент является подтипом целевого, т.е. может содержать больше аттрибутов.
А во-вторых, у тебе есть требуемая возможность — определяй себе на здоровье static bool operator==(T a, T b) {...}
-----
А фатанатичное стремление соблюдать LSP вообще не понимаю. Согласен лишь с тем, что несоблюдение принципа может привести к популярным ошибкам проетиктирования (наиболее популярная — неоправданное увеличение связанности и последующая трудность независимого развития частей системы), однако его строгое соблюдение так же может спровоцировать лишние телодвижения на ровном месте. ИМХО, зачастую принадлежность некоей классификации удобней устанавливать напрямую через аттрибуты состояния (виртуальные), чем через сетку двойных диспечеризаций и прочих "посетителей".
Простой пример, предположим есть поток, у потока есть метод "Seek(args)", и парный аттрибут "bool CanSeek". Яркий пример нарушения LSP, тем не менее крайне удобный для использования, позволяющий одним if-ом выбрать наиболее подходящий способ работы с потоком.
Так что если нарушение LSP в конкретных случаях не добавляет связанности, но упрощает представление алгоритмов, то почему бы и нет? В обсуждаемом Equals(arg) мы обычно приводим к тому типу, коим являемся, т.е. связанность увеличиться никак не может, наоборот, может резко снизиться, за счёт использования методов уровня базового фреймворка.
Здравствуйте, vdimas, Вы писали:
V>Простой пример, предположим есть поток, у потока есть метод "Seek(args)", и парный аттрибут "bool CanSeek". Яркий пример нарушения LSP, тем не менее крайне удобный для использования, позволяющий одним if-ом выбрать наиболее подходящий способ работы с потоком.