LINUX.ORG.RU

ООП. Как представляете себе идеальную реализацию?

 , ,


2

3

Я знаю как минимум 4 слабо совместимых друг с другом понятия ООП:

  • С++: класс = неймспейc, вызов метода через точку,
  • CLOS: класс = идентификатор + наследование, тело метода определяется по классу всех параметров (а не только первого), методы доопределяются модификаторами :after :before :around.
  • Racket: класс = first-class object, как и функция, соответственно, может доопределяться по месту и не иметь имени.
  • Haskell: классы типов как наборы операций над типам (которые можно считать эквивалентными классам других языков)

Хотелось бы узнать, какой подход вам ближе и почему. А также, можно ли из упомянутых видов получить некую «идеальную реализацию» и какой синтаксис мог бы быть у такой реализации.

★★★★★
Ответ на: комментарий от anonymous

можно сохранить определение класса в переменную.

Зачем?

Что б декларировать его в произвольном окружении. Очевидно же.

no-such-file ★★★★★
()
Ответ на: комментарий от anonymous

В крестах перегрузка бесплатна во время исполнения.

Да. А что?

no-such-file ★★★★★
()
Ответ на: комментарий от anonymous

Мультиметоды - это не ООП, это просто динамическая диспетчеризация по значениям/типам аргументов функции

угу, а обычные методы --это не ООП, это просто динамическая диспетчеризация по первому аргументу

И единственный истинный ООП — это Smalltalk, потому как у него нет ни методов ни мультиметодов, а есть сообщения :-)

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

истинный ООП — это Smalltalk, потому как у него нет ни методов ни мультиметодов, а есть сообщения

Те же методы - вид сбоку.

no-such-file ★★★★★
()
Ответ на: комментарий от mv

Precedence order можно оговорить.

Для произвольных типов? Заранее? Пока никто не придумал как. Если напишешь однозначную функцию которая позволяет однозначно отсортировать любое множество типов CL, то я для тебя лично напишу дополнение к CLOS, которое позволит определять методы на типах.

Есть же у дженериков квалификатор equal?

Это ты про что? Если про (eql ...), то он по определению меньше любого типа. А два разных eql никак пересечься не могут.

monk ★★★★★
() автор топика
Ответ на: комментарий от no-such-file

Те же методы - вид сбоку.

Ну не скажи. В C++ obj.undefined_method() не скомпилируется, а если передашь сообщение, то просто получишь ответ «no-such-method», который можно штатно обработать. Что позволяет писать функции в стиле «передадим аргументу функции сообщение1. Если у него нет такого метода, передадим сообщение2».

monk ★★★★★
() автор топика
Ответ на: комментарий от no-such-file

Метод - это (одна из возможных) реакций на прием сообщения.

anonymous
()
Ответ на: комментарий от no-such-file

Да не, есть приличные. Кроме того, есть open methods Страуструпа. Может даже в следующем стандарте будут.

anonymous
()
Ответ на: комментарий от monk

Мультиметоды, в отличие от методов, не принадлежат объекту и не от него пляшут. Так что не объектно-ориентированная фича получается.

anonymous
()
Ответ на: комментарий от anonymous

Через шаблоны,

Гм. Есть функция

Object *deserialize(string file);

тебе надо вызвать метод new_run(), а если он на этом потомке Object не определён, то run(). Покажи, как ты это сделаешь на C++.

monk ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Можно пример?

loadConfigFromDatabase();

и получили ORM частично сгенерированный по структуре БД, частично из этой БД загруженный.

monk ★★★★★
() автор топика
Ответ на: комментарий от anonymous

В С++, хвала Аллаху, нет никаких Object'ов.

Ну как же нет? public ref class Object в MS C++, qt-project.org/doc/qt-4.8/qobject.html‎ , TObject в C++ Builder, CObject в MFC, ... тысячи их!

В данном случае просто возвращается некий потомок некоторого класса Object (для определённости). Если тебе удобней, пусть возвращается void*, это несущественно.

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

тебе надо вызвать метод new_run(), а если он на этом потомке Object не определён, то run(). Покажи, как ты это сделаешь на C++.

так же как и в лиспах - поверх ЯП пишется надстройка, и будет не прямой вызов метода, а по имени

wota ★★
()
Ответ на: комментарий от monk

Не в MS C++, а в C++/CLI. Т.е. реализации под .NET. Говнобиблиотеками, вроде Qt не интересуюсь. Гуйню не пишу. void * - это не Object. top-тип(см.TAPL), как максимум. И то, только для указателей.

ИМХО, ты склонен к излишним обобщениям ;)

Что касается твоего вопроса - никак. Только если такую возможность предусмотрел разработчик базового класса.

anonymous
()
Ответ на: комментарий от wota

поверх ЯП пишется надстройка

На C++ разве так можно? Или это уже не C++, а некий язык написанный на нём (например лисп :-))) ?

А вообще, Анонимус обещал:

В С++ это можно сделать в статике. Через шаблоны, SFINAE и enable_if.

Хочу это видеть.

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

Так зачем там именно классы(напомню, что речь о языке со статической типизацией)? Они не дают никаких преимуществ. Сделай простые «словари»(как, в принципе и реализовано ООП во всяких питонах), например.

anonymous
()
Ответ на: комментарий от monk

А почему это нельзя в С++?

Что касается моего обещания - я имел в виду, конечно же, статику. В динамике через обертки некоторые, да.

anonymous
()
Ответ на: комментарий от monk

На C++ разве так можно?

конечно, никто не запрещает свою модель ООП реализовать. вон на С, например, такую сделали

Или это уже не C++, а некий язык написанный на нём (например лисп :-))) ?

лисп, если что, не умеет ООП

wota ★★
()
Ответ на: комментарий от anonymous

Сделай простые «словари»

В «словарь» надо будет внести описание типов полей объектов и методов (методы нужны, так как именно в них описана логика получившихся классов, их пользовательский интерфейс и т.д.). Фактически это будет реализованная вручную система классов.

monk ★★★★★
() автор топика
Ответ на: комментарий от wota

лисп, если что, не умеет ООП

Даже если ты не считаешь CLOS за OOP, так на нём есть куча других реализаций и в стиле смолтолка и в стиле C++ в том числе.

monk ★★★★★
() автор топика
Ответ на: комментарий от wota

вон на С, например, такую сделали

То есть те классы, что встроены в C++ не использовать... ну да... а зачем тогда C++? Достаточно обычного C.

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

Для произвольных типов? Заранее? Пока никто не придумал как.

Да хоть в порядке объявления. Или список весов задавать.

Если напишешь однозначную функцию которая позволяет однозначно отсортировать любое множество типов CL, то я для тебя лично напишу дополнение к CLOS, которое позволит определять методы на типах.

И? Посыл-то был в том, что deftype и CLOS не дружат.

mv ★★★★★
()
Ответ на: комментарий от monk

Даже если ты не считаешь CLOS за OOP, так на нём есть куча других реализаций

я считаю его за ООП, но это все-равно, что сказать, что все реализации ООП - это реализация С, т.к. на C есть надстройка в виде gobject

wota ★★
()
Ответ на: комментарий от monk

То есть те классы, что встроены в C++ не использовать...

использовать, на них будет гораздо проще и удобнее сделать реализацию, чем на голом С

wota ★★
()
Ответ на: комментарий от mv

Посыл-то был в том, что deftype и CLOS не дружат.

Подружить можно. Нельзя однозначно выбрать метод, если он определён на типе, а не на классе.

Да хоть в порядке объявления. Или список весов задавать.

Хех. Я почти такое для Racket проектировал (только считал, что чем позже объявлено, тем раньше должно быть проверено, чтобы доопределять/уточнять было можно). Реализация почти тривиальна: с дженериком ассоциируем список. defmethod добавляет в список проверку через (lambda (...) (and (typep ...) (typep ...))). При вызове проверяются все условия по порядку до первого сработавшего. Всё.

Можно даже круче сделать: цеплять методы к произвольному условию на аргументы.

Если оно кому-то надо, могу реализовать и выложить на github.

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

Если оно кому-то надо, могу реализовать и выложить на github.

Оно в стандарте надо. Оно - или «всё есть класс», или чтобы компаундные типы CLOS'ом понимались.

mv ★★★★★
()
Ответ на: комментарий от monk

то просто получишь ответ «no-such-method»

Так и в крестах ты получишь тот же ответ. Только на этапе компиляции - и это хорошо.

«передадим аргументу функции сообщение1. Если у него нет такого метода, передадим сообщение2».

Можно так делать на шаблонах.

no-such-file ★★★★★
()
Ответ на: комментарий от anonymous

Можно пример?

Примеры выше в треде. Там про racket кажется речь была. И вообще, это не ко мне - я напротив, спрашивал в каком таком языке есть подобный изврат.

no-such-file ★★★★★
()
Ответ на: комментарий от wota

лисп, если что, не умеет ООП

лисп не умеет, Common Lisp умеет, ибо часть стандарта.

все-равно, что сказать, что все реализации ООП - это реализация С, т.к. на C есть надстройка в виде gobject

Слава гомоиконности в CL надстройка неотличима от встроенных возможностей.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

лисп не умеет, Common Lisp умеет, ибо часть стандарта.

я имел ввиду «голый» ЯП без надстроек, пусть и стандартных, т.к. выше шел разговор именно про надстройки, а так - CLOS действительно хорош и действительно часть стандарта

Слава гомоиконности в CL надстройка неотличима от встроенных возможностей.

самый главный и очевидный недостаток - эффективность, пока еще надо о ней думать, и тут CLOS очень плох

wota ★★
()

Как представляете себе идеальную реализацию?

Все есть объект + смешанная реализация: методы могут как принадлежать определенным классам (типам), так и специализироваться на них, а-ля мультидиспатч с, желательно, бесконечно (на сколько хватит фантазии и семантики конкретно яп) расширяемой системой свойств, по которым мультиметод может специализироваться. Отдельные пространства имен для «обычных» методов и мультиметодов, и вообще - побольше автоматически порождаемых пространств имен.

alienclaster ★★★
()
Ответ на: комментарий от alienclaster

Еще конечно же нужна возможность явно задать конструкторы-деструкторы. И, скорее всего, такая система будет прототипной...

alienclaster ★★★
()
Ответ на: комментарий от wota

я имел ввиду «голый» ЯП без надстроек, пусть и стандартных, т.к. выше шел разговор именно про надстройки

А вы как определяете, что надстройка, а что нет?

недостаток - эффективность, пока еще надо о ней думать, и тут CLOS очень плох

Ну так там сплошная динамика - за все надо платить.

no-such-file ★★★★★
()

кури Акторы

там явно постулируется что скорость взаимодействия конечна и нет всеведующего cpu который аля лапласова? механическая вселеная обсчитывается основываясь на знании всех координат и импульсов.

кури Акторы - это реальные абстракции

а ООП так секстанство одно.

qulinxao ★★☆
()
Ответ на: комментарий от alienclaster

Деструкторы ставят крест на нормальном GC. А без GC получится лишь минимальный ООП, вроде плюсового.

anonymous
()
Ответ на: комментарий от anonymous

Деструкторы ставят крест на нормальном GC. А без GC получится лишь минимальный ООП, вроде плюсового.

Вариант без GC не интересен, а деструкторы могут быть а) необязательными б) помогать, подсказывать, когда освобождать внешние, системные ресурсы.

Кроме того, «среда» (компилятор, рантайм) может сама выбирать оптимальный вариант, либо иметь возможность настройка для выбора стратегии действий.

alienclaster ★★★
()
Ответ на: комментарий от alienclaster

Да зачем такие деструкторы? Вполне достаточно паттерна с локальным захватом ресурса. with* функции в Haskell, with-* функции в CL, но лучше что-нибудь более обобщенное вроде using в С#, try-with-resources в Java или with в Python. И с GC все ок и ресурсы освобождаются и код прозрачен. Может деструкторы и крутая штука, но только полноценно они могут работать только там, где GC нет или он опционален/частичен (как в C++/CLI, например).

По поводу компилятора - не понял. Вы про вывод регионов что ли? Или о чем? Вывод регионов в ООП тоже весьма проблематичен из-за вездесущего позднего связывания.

anonymous
()
Ответ на: комментарий от anonymous

Вполне достаточно паттерна с локальным захватом ресурса. with* функции в Haskell, with-* функции в CL

Это как раз неудобные варианты, другое дело - python, C# и сотоварищи

зачем такие деструкторы?

А зачем они, например, в C# (или они там правильно называются финализаторами)? Или там что-то не так с GC?

И с GC все ок и ресурсы освобождаются и код прозрачен

Деструкторами можно кастомизовать освобождение ресурсов и, как я уже сказал, давать «подсказки» GC. И под ресурсами я тут понимаю не память, занимаемую внутренними объектами, а внешние «системные» ресурсы - дескрипторы файлов, соединения с бд, сетевые соединение итд.

По поводу компилятора - не понял. Вы про вывод регионов что ли? Или о чем?

А что конкретно непонятно? Тут у нас тред о «желанном ооп», так вот я в довесок хочу еще и динамически настраиваемый рантайм, а что, имею право :)

alienclaster ★★★
()
Ответ на: комментарий от alienclaster

Финализатор и деструктор - разные вещи. Первый вызывается в GC(через одно место) и имеет кучу проблем(начиная с того, что полей уничтожаемого объекта может уже давно не существовать, заканчивая отсутствием гарантии вызова - да, да - финализатор могут вообще не вызвать). Концепция с паттерном dispose хоть и костыльна(на фоне полноценного RAII С++), но в итоге смотрится гораздо лучше. Если это будет из коробки, то как таковой финализатор не нужен. И я бы предложил для собираемых объектов с невызванным(но нужным) dispose ругаться в какой-нибудь лог(или каким-то иным образом сообщать о проблеме), а финализатор сам по себе не предоставлять. Если у тебя ресурс - используй using/try-with-resources/with. Захватил ресурс и не отпустил - ай-яй-яй тебе - ругаемся при сборке на такой объект(ладно-ладно, можно там и вызвать этот самый dispose), т.к. это баг.

По поводу настраиваемости рантайма. GC весьма вредная зараза, распростроняющаяся на всю архитектуру... Если он у тебя работает для всех объектов, ты уже не властен над временем их жизни... Так что или руками/RC или полноценный GC, или отделньные типы ссылок/отдельные кучи, как в modula2 или C++/CLI.

anonymous
()
Ответ на: комментарий от wota

я имел ввиду «голый» ЯП без надстроек, пусть и стандартных,

Взрыв мозга. Что ты имеешь в виду под «голым ЯП»? Если следовать твоим рассуждениям, то CL - это те три экрана кода, в которые минимальный REPL умещается.

mv ★★★★★
()
Ответ на: комментарий от anonymous

По поводу настраиваемости рантайма. GC весьма вредная зараза, распростроняющаяся на всю архитектуру... Если он у тебя работает для всех объектов, ты уже не властен над временем их жизни...

И слава Небесной Дискете! Пока ссылочка есть, всё присутствует, ну а неопределённость, когда финализация вызовется на подвисший в лимбе объект- тут можно и RAII with-макрос наклепать.

В энтерпрайзном C/C++ самая распространённая ошибка - кто-то насилует мёртвую ссылку. Нафиг бы такая власть... Это реально миллионы долларов стоит.

mv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.