Здравствуйте, A13x, Вы писали:
A>В java и .NET есть базовый класс Object с определенным методом equals (Equals в C#) с сигнатурой: A>Предположим, что мы делаем некоторый язык, скажем E, похожим насколько возможно на java/C#, в котором хотим описать каким-то образом типобезопасный equals.
В новом языке не надо делать общий базовый класс — это просто глупо. Пусть программист осознанно обогащает свои классы реализуя необходимые интерфейсы.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, A13x, Вы писали:
A>>...
MTD>В новом языке не надо делать общий базовый класс — это просто глупо. Пусть программист осознанно обогащает свои классы реализуя необходимые интерфейсы.
Это спорное утверждение
Отчасти я с ним согласен с точки зрения "обогащения" функционала, но все же я считаю, что базовый класс необходим, но только с одним методом — getClass() или getTypeMirror() — последнее это из альтернативной модели RTTI — Type Mirror.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, A13x, Вы писали:
A>>я считаю, что базовый класс необходим
MTD>Ты уверен, что кастрюля и ворона имеют одного предка?
Ну это уже софистика. В определенных задачах — думаю да, в некоторых задачах это возможно вообще будет один и тот же объект.
В данном случае базовый класс не имеет отношения к предметной области, а скорее к объектной модели ядра языка. Мне кажется, проводить такие параллели не совсем корректно.
Здравствуйте, A13x, Вы писали:
MTD>>Ты уверен, что кастрюля и ворона имеют одного предка?
A>Ну это уже софистика. В определенных задачах — думаю да, в некоторых задачах это возможно вообще будет один и тот же объект.
void* в C, Object в Java — это просто дыра в безопасности, при отсутствии ощутимой выгоды. Ну вот зачем тебе возможность скастить кастрюлю в ворону? Какие такие "определенные" задачи?
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, A13x, Вы писали:
MTD>>>Ты уверен, что кастрюля и ворона имеют одного предка?
A>>Ну это уже софистика. В определенных задачах — думаю да, в некоторых задачах это возможно вообще будет один и тот же объект.
MTD>void* в C, Object в Java — это просто дыра в безопасности, при отсутствии ощутимой выгоды.
Для С — согласен, для Java — не понимаю — почему сделан такой вывод. void* не хранит информации о типе и нет возможности выполнить safe cast, для Object это не так, что меняет дело, разве нет?
Здравствуйте, A13x, Вы писали:
A>Для С — согласен, для Java — не понимаю — почему сделан такой вывод. void* не хранит информации о типе и нет возможности выполнить safe cast, для Object это не так, что меняет дело, разве нет?
Любой каст — потенциальная ошибка. По мне так лучше во время компиляции будет проверен тип, нежели в рантайме полетит исключение.
Про "особые" случаи поделитесь?
Здравствуйте, MTD, Вы писали:
MTD>...
MTD>Любой каст — потенциальная ошибка. По мне так лучше во время компиляции будет проверен тип, нежели в рантайме полетит исключение. MTD>Про "особые" случаи поделитесь?
Мне представляется, что это было бы полезным для AOP (см. например тут). Например аспект логирования — для описания обобщенного обработчика логгера удобно оперировать такой конструкцией:
public void before(JoinPoint joinPoint) {
final Object[] args = joinPoint.getArgs();
//...if (args.length > 0) {
boolean next = false;
for (final Object arg : args) {
if (next) {
stringifier.append(", ");
} else {
next = true;
}
stringifier.append(arg);
}
}
//...
}
Здравствуйте, A13x, Вы писали:
A>Например аспект логирования — для описания обобщенного обработчика логгера удобно оперировать такой конструкцией:
Для этого случая Object совершенно не оправдан. Какие типы объектов можно передать в логгер? Очевидно, те которые можно напечатать. Поэтому логично работать с интерфейсом, скажем Printable.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, A13x, Вы писали:
A>>Например аспект логирования — для описания обобщенного обработчика логгера удобно оперировать такой конструкцией:
MTD>Для этого случая Object совершенно не оправдан. Какие типы объектов можно передать в логгер? Очевидно, те которые можно напечатать. Поэтому логично работать с интерфейсом, скажем Printable.
А если сервис сторонний, а логировать хочется? Писать сервис-делегат с адаптерами поверх non-printable объектов?
Вообще, мы несколько отклонились от темы — предлагаю отделить ветку с названием вида — "Нужен ли единый базовый класс".
Здравствуйте, A13x, Вы писали:
MTD>>Для этого случая Object совершенно не оправдан. Какие типы объектов можно передать в логгер? Очевидно, те которые можно напечатать. Поэтому логично работать с интерфейсом, скажем Printable.
A>А если сервис сторонний, а логировать хочется? Писать сервис-делегат с адаптерами поверх non-printable объектов?
Для этого случая и так и так придется совершить телодвижения, так как автоматически сгенеренный toString выведет совсем не то, что тебе интересно.
A>Вообще, мы несколько отклонились от темы — предлагаю отделить ветку с названием вида — "Нужен ли единый базовый класс".
Здравствуйте, MTD, Вы писали:
A>>я считаю, что базовый класс необходим
MTD>Ты уверен, что кастрюля и ворона имеют одного предка?
Кастрюля — слово из восьми букв, ворона — слово из шести букв. А, вы на них не смотрите как на слова? Ну вот и на GetType() смотрите не как на реальное свойство вороны или, там, коровы, а как на чисто техническое, которое упихали туда же, куда и настоящие свойства. Испортили чистоту моделирования, но ведь в наших программах мы все еще имеем дело со словами, а не с реальными объектами. Куда деваться.
Здравствуйте, MTD, Вы писали:
MTD>В новом языке не надо делать общий базовый класс — это просто глупо. Пусть программист осознанно обогащает свои классы реализуя необходимые интерфейсы.
Ага, конечно! Все кругом дураки, один MTD у нас самый умный, надо было у него спросить создателям Java/.NET. Как домашнее задание, предлагаю подумать на тему, почему все современные языки делают именно один общий базовый класс. Еще предлагаю подумать в качестве подсказки на тему, почему в C++, где нет единого общего корня, разные библиотеки так или иначе создают один базовый класс и какие недостатки у такого подхода.
Здравствуйте, iLikeCookies, Вы писали:
LC>Здравствуйте, MTD, Вы писали:
MTD>>Ты уверен, что кастрюля и ворона имеют одного предка?
LC>Имеют, они оба материальные объекты реального мира. Они даже имеют общие атрибуты, такие как вес, плотность итд.
Тогда надо создавать предка "Материальный объект реального мира" и наследовать от него кастрюлю с вороной. А глобальный общий предок не нужен.
Здравствуйте, iLikeCookies, Вы писали:
LC>Как домашнее задание, предлагаю подумать на тему, почему все современные языки делают именно один общий базовый класс.
Я считаю, что это неправильное решение.
LC>Еще предлагаю подумать в качестве подсказки на тему, почему в C++, где нет единого общего корня, разные библиотеки так или иначе создают один базовый класс и какие недостатки у такого подхода.
Ну вот пусть и создают базовый класс там, где он нужен, а в язык его пихать зачем?
Здравствуйте, iLikeCookies, Вы писали:
LC>Еще предлагаю подумать в качестве подсказки на тему, почему в C++, где нет единого общего корня, разные библиотеки так или иначе создают один базовый класс и какие недостатки у такого подхода.
А нет никаких недостатков. Зато есть преимущество, когда эти базовые классы из разных библиотек, и не имеющих между собой ничего общего, не скрещиваются насильно.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, A13x, Вы писали:
A>Отчасти я с ним согласен с точки зрения "обогащения" функционала, но все же я считаю, что базовый класс необходим, но только с одним методом — getClass() или getTypeMirror() — последнее это из альтернативной модели RTTI — Type Mirror.
Чем это лучше , дать програмиств решать наследоваться от этого интерфейса или нет ?
Здравствуйте, iLikeCookies, Вы писали:
LC>Еще предлагаю подумать в качестве подсказки на тему, почему в C++, где нет единого общего корня, разные библиотеки так или иначе создают один базовый класс и какие недостатки у такого подхода.
MTD,
A>>В java и .NET есть базовый класс Object с определенным методом equals (Equals в C#) с сигнатурой: A>>Предположим, что мы делаем некоторый язык, скажем E, похожим насколько возможно на java/C#, в котором хотим описать каким-то образом типобезопасный equals.
MTD>В новом языке не надо делать общий базовый класс — это просто глупо. Пусть программист осознанно обогащает свои классы реализуя необходимые интерфейсы.
В силу того, что система типов в java и c# номинативна и используется полиморфизм, основанный на наследовании, такой подход будет ещё более глупым — он просто породит дублирование — появление тьмы классов-пустышек с одинаковой базовой сигнатурой, отличающимися только именами.
Нечто подобное уже произошло в C# с делегатами, и ничего хорошего в этом нет.
Когда ты определяешь класс X, мысли это как набор предположений обо всех объектах данного класса.
Тогда Object — это класс, об объектах которых нельзя сделать никаких, кроме самых общих, верных для данного рантайма, предположений.
И не забывай, что классы и объекты формируют модель, она совсем не обязана отражать объекты реального мира, тем более 1:1 или даже n:m. То есть всегда найдётся предметная область (и ты наверняка сталкивался), когда для реального объекта создаются множество взаимодействующих классов, для подавляющиего большинства реальных объектов классы не создаются вообще, и часто создаются синтетические классы, не имеющие никакого отражения в реальном мире, несмотря на то, что сама модель может иметь прямое отношения к реальным объектам.
В этом свете введение класса Object позволяет получить определённые выигрыши, причём недостатками можно пренебречь.
Среди выигрышей:
1. определение функций, которые выполняют общие трансформации кода работающие для любых объектов (рефлекшн, рантайм-макросы)
2. определение функций, принимающих любой объект или последовательность объектов (например, логгер, Runnable)
3. определение функций, возвращающих любой объект (например фабрики, ioc контейнеры)
При достаточно развитой системы типов, некоторые из определений возможно бывает написать без object, используя разные продвинутые конструкции (см. например опредление функции map в Scala), но в общем случае нет.
Также из-за перегрузки становится невозможным описать тип "функция, принимающая любое количество любых аргументов", вместо этого в библиотеках постоянно фигурируют fun(a1); fun(a1, a2); ... fun(a1, a2, ..., a100500), я нахожу этот момент крайне неудобным. Какое это имеет отношение к топику? А такое, что понятие "список аргументов функции" не является объектом, и это порождает определённые неудобства, которые вполне реальные, в отличие от эфемерных концептуальных вопросов "может ли объект Ворона1 с состоянием Сыр-в-клюве принимать сообщение Каркать?"