LINUX.ORG.RU
ФорумTalks

Почему боятся ООП?

 


0

6

Заметил, что некоторые разрабы стесняются (триггерятся/истерят/брезгуют/отстраняются/впадают_в_кому от) ООП. Почему? Вот, один говорит «у нас тут не наследование, а …», так и хочется добавить «розовые пони». Т.е. если ты можешь реализовывать интерфейсы, у тебя уже нет отношения is-a? Может быть, какие-то древние ЯП не поддерживали чисто виртуальные интерфейсы, и нужен был непременно базовый класс, но как минимум уже C++ сломал эту традицию.

★★★★★

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

Ну начал копипастить вики, копипасть до конца

«Практически все лазерные принтеры 1990-х годов поддерживали PostScript в качестве основного языка»

А поэтому они тупо забили на поддержку новых версий

Да. Но не наговнокодили, а родили другое промежуточное представление

«Таким образом, PostScript вытесняется из офисов языком PCL»

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

Изобрели два промежуточных ЯП. И теперь нужно как для первого код поддерживать, так и для второго писать? Молодцы, «не наговнокодили». Количество классов для двух промежуточных форматов сам посчитаешь или мне посчитать? А потом, ещё посчитай когда твои макаки изобретут 3-й промежуточный формат. Чатгпт их много выдала, там больше 3. Кто знает какой будет следующий в тренде?

foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 3)
Ответ на: комментарий от foror

Так чтобы с этими состояними эффективно работать нужная целая СУБД и язык запросов SQL.

Нет. Легко делается реализация в памяти с индексами.

Работают такие состояния на порядки медленне состояний на переменных или структурах.

Тоже нет. Строку таблицы не приходится создавать на куче как объект. Обработка колонки таблицы не требует нелокального перехода по ссылке на каждую строку. Индексы можно сделать по любой колонке или их комбинации, а не только по идентификатору строки-объекта.

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

PostScript

Почему-то перед генерацией этого постскрипта в LaTeX приходится выбрать модель принтера. Иначе вместо изображения ужас получается.

И штрихкоды разве PostScript умеет? В смысле, как из него потом в EZPL преобразовывать?

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

Нет. Легко делается реализация в памяти с индексами.

Это обычная hashmap или treemap. Опять частный случай ООП.

Строку таблицы не приходится создавать на куче как объект.

Да кто вам сказал, что объекты обязаны на куче создаваться? Если макаки не могут нормальный компилятор вам сделать, это не значит, что в ООП только на куче объекты создавать можно.

таблицы не требует нелокального перехода по ссылке на каждую строку

Рука лицо. Ладно я устал, я мухожук. Удачи.

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

Если макаки не могут нормальный компилятор вам сделать, это не значит, что в ООП только на куче объекты создавать можно.

Это же Вы джаву в пример приводили. Как в ней сделать сотню объектов так, чтобы скорость

s = 0;
for(Obj o : objects) {
  s += o.getSum();
}

была не ниже, чем

s = 0;
p = &tab[0].sum;
for(int i = 0, i <= n; i++)
{
  s += *p; p += ROWSIZE;
}

?

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

Redux

Частный случай ООП

Nyet. Это частный случай механизма для управления изменяемым состоянием (здорового человека). Мешанина из взаимосвязанных (во многих смыслах) объектов в этом вашем ООП — тоже механизм для управления изменяемым состоянием (курильщика).

Видим объекты, видим методы

— Ты методы видишь? И я нет. А они есть!

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 2)
Ответ на: комментарий от FishHook

мультиметод

перекомпилировать ядро под каждое поделие сумрачного китайского гения

Не надо никого перекомпилировать, просто пишешь ещё один метод под новую комбинацию параметров. Старые методы остаются как были, их вообще трогать не нужно.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от monk

obj.meth(arg1, arg2, …) против meth(obj, arg1, arg2, …). Одно и то же.

В контексте оно может и одно и тоже. Но так-то разница есть:

  1. Метод позволяет инкапсулировать данные объекта, а функция нет.
  2. Автодополнение в первом случае проще и логичнее.
  3. 25 < 26.

Раньше по теме ещё было, что класс и модуль - одно и то же, с разным синтаксисом. Но у модуля же нет экземпляров (или один экземпляр). У класса может быть множество экземпляров. И поведение экземпляров может отличаться.

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

ващет у Кнутия «во времена» до структурные работа с массивами наборов синтаксически как набор массивов

как в обьектном подходе который тяготеет к pod+механизм резолва методов минимизировать количество разыменнований при обращении к полям?!

один из методов (см Елизарова кстати с hft на как раз таки джабе)

перевод массива объектов в обьект массивов

а так то да всё есть ООП

qulinxao3
()
Ответ на: комментарий от Kogrom
  1. Почему? Данные в обоих случая в obj. Более того, в случае функции я могу написать
struct myObject;

struct myObject *obj = createObj(...);
meth(obj, ...);

а в случае класса я обязан писать поля класса в .h и перекомпилировать все программы, использующие класс, если у него добавилось поле или изменился тип поля. Или добавился метод. Поэтому инкапсуляция лучше через функции.

  1. Согласен. Наверное, единственный объективный плюс методов через точку по сравнению с обобщёнными функциями.

  2. Можно тоже писать без пробелов: meth(obj,arg1,arg2,…)

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

Это же Вы джаву в пример приводили. Как в ней сделать сотню объектов так, чтобы скорость

Использовать Foreign Functions & Memory API подвезённый в последние версии. По сути вы вручную запрашиваете у ОС память и размещаете свои данные. Дальше задаёте структуру и выравнивание полей. А затем как в Си работать. Можно даже AVX инструкции использовать.

А чтобы упростить и сделать удобно (в ООП парадигме) у меня даже фреймворк запилен, который оборачивает такую структуру в класс, в котором просто указатель на нужное смещение и методы для работы с полями этой структуры по нужным смещениям (генерится автоматом).

К сожалению, сейчас я только в класс могу обернуть этот указатель и положиться на JIT (оптимизирует размещение класса на стэк). В принципе, в джаве ожидается запиливание примитивных классов без накладных расходов, тогда это вообще будет огонь.

foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от foror

Использовать Foreign Functions & Memory API

Из этого сделать объект Java не получится нормально.

Дальше задаёте структуру и выравнивание полей.

Ну вот. То есть, если надо быстро, то никаких объектов. Только данные.

который оборачивает такую структуру в класс, в котором просто указатель на нужное смещение.

Так тут должна быть коллекция объектов. В ООП языках почти наверняка, даже если делать массив структур, то элементом массива будет не структура, а указатель. Плюс обязательный доступ через объект не даёт идти по колонке с полями, даже если их адреса известны.

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

Ну вот. То есть, если надо быстро, то никаких объектов. Только данные.

Так вы чем читаете? Я и говорю, что ООП гибче. Если нужно удобно юзаем классы, если нужно быстро юзаем структуры. То, что в джаве до этого не сразу доперли, так это издержки реализации. В том же сишарпе это из коробки давно есть.

В ООП языках почти наверняка, даже если делать массив структур, то элементом массива будет не структура, а указатель

Я же говорю в джаве ожидаются примитивные классы, когда будет не массив указателей на объекты, а массив классов-значений. Тогда вообще будет огонь, в частности для моего фреймворка. Но это издержки реализации, а не конкретно ООП.

foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 3)
Ответ на: комментарий от foror

Я и говорю, что ООП гибче.

Это ООП:

По сути вы вручную запрашиваете у ОС память и размещаете свои данные. Дальше задаёте структуру и выравнивание полей. А затем как в Си работать. Можно даже AVX инструкции использовать.

???

Но это издержки реализации, а не конкретно ООП.

Строки как данные всё равно заметно отличаются от объектов ООП. В частности, если в разных строках разные типы данных, то просто будет дополнительная колонка «тип», но у каждой строки будут все колонки всех допустимых типов.

Ещё есть объекты не ООП. Например, в Haskell. Состояния в монадах, для обработки изменения состояний есть удобные интерфейсы (do, линзы, …), явное указание наличия или отсутствия изменения состояния позволяет на порядок упростить тестирования (вплоть до генерации случайных тестов по указанию инварианта в комментарии).

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

Это ООП

Да. Все операции происходят в ООП парадигме. Подробнее в документации Foreign Functions & Memory API.

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

могут ли маски обьектов быть переплетёнными что бы из имея массив обьектов получить локальность по каждому полю?

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

т.е обьекты фиктивно разряжены и как результат каждое отдельное поле F у массива обьектов сгрупированно:

обьявленно [3]obj

obj это f,i,e,l,d

однако в памяти поля расположаться так:

f[0],f[1],f[2],e[0],e[1],e[2] .....d[2]

qulinxao3
()
Последнее исправление: qulinxao3 (всего исправлений: 1)
Ответ на: комментарий от monk

Почему? Данные в обоих случая в obj.

Если мы просто пишем отдельную функцию, то структура будет вся открыта на изменение кем попало. Если мы создаём полноценный класс, то недостатки вылезут в других местах:

  1. Запись конструктора будет длиннее.
  2. Надо будет во всех функциях (имитирующих методы) использовать внутри этот указатель на структуру для доступа к полям (хотя в Питоне так и делают и никто особо не страдает).
  3. Деструктор надо будет вызывать явно.
  4. Придётся использовать указатели. При использовании классов они нужны не всегда.

Можно тоже писать без пробелов: meth(obj,arg1,arg2,…)

Можно. Про 25 < 26 я пошутил. Надо был смайлик поставить.

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

Я бы запилил нечто подобное в синтаксисе ЯП:

kennel.add(dog)
...

Iterator<Dog<::name>> it = kennel.iterator(Dog::name)
...

Dog<::name> entry = it.next()
print(entry)

Не знаю, нужно ли тебе сразу итерации по нескольким полям, но можно сделать так:

Iterator<> it = kennel.iterator(Dog::[name, sex])
Dog<::[name, sex]> entry = it.next()
print("${entry.name()}: ${entry.sex()}")

Изначально объект создаётся по классике. Но в хранилище он разбивается по твоему принципу. Ну, либо в самом ЯП нужно при создании добавлять тип хранения полей. Можно тоже в синтаксис это внедрить:

Dog:: dog = Dog::.new()

Array<Dog::> ...
foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от foror

тож вариант

впрочем!

в отсутствии jvm-филии

возникает очучение очередного извода плюсов ( для олдов pl/1 и algol-68) можно всё - мы за ценной не постоим

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

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

Если она не иммутабельная, конечно.

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

кста аспекты ща как в джава мире?

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

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

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

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

struct myObject *obj = createObj(...);
meth(obj, ...);
  1. Разве?
auto with_class = new MyClass(arg1, arg2, ...);
auto wo_class = MyStruct(arg1, arg2, ...);
  1. В паскале есть with, в лиспе with-slots.

  2. В Java его тоже надо вызывать явно. А не в Java есть финализаторы в языках со сбором мусора и вызов деструктора при выходе из области видимости. В Си в любом случае надо освобождать память, поэтому деструктор вызовется.

  3. А как можно сделать класс без указателя, если доступ к полю производится через указатель на объект + смещение? Если речь про то, что объект можно разместить на стеке, то для структуры тоже можно, если сделать конструктор, использующий alloca. Зато при добавлении поля в структуру в библиотеку не надо перекомпилировать программу, которая использует эту библиотеку.

monk ★★★★★
()
Ответ на: комментарий от monk
  1. … В gcc есть __attribute__((cleanup)). Можно деструктор указать при инициализации.
monk ★★★★★
()
Ответ на: комментарий от qulinxao3

Обмазываются спрингом во все поля. Который аспектам обмазан с головы до ног. Но как там в сбере или амазоне я не в курсе. Знаю, что местный @stevejobs из сбера тюхнул поседев от легаси спринга. А у меня свой путь, пользую свои фреймворки, работаю вообще в другой сфере, не разрабом. А будет время ещё и свой ООП ЯП запилю вместе с заинтересованным сообществом, чтобы всякие джавы с крестами и прочиями сями похоронить.

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

А будет время ещё и свой ООП ЯП запилю вместе с заинтересованным сообществом, чтобы всякие джавы с крестами и прочиями сями похоронить.

а зачем, если и так ЯП после пика C++ появилось уже так много, и они всё, что можно у условного рынка C++ уже отъели?

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

Ну, это как если бы ты был дорвейщиком/seo оптимизатором и спросил: Зачем нам gpt 3.5, мы и на байесовых алгоритмах неплохо ботаников из гугла опускаем. А оно вон как вышло.

foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 1)
Ответ на: комментарий от monk

Я же привёл пример

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

  1. Разве?

Я тоже в такие игры умею играть:

MyClass with_class = {arg1, arg2, ...};
auto wo_class = MyStruct(arg1, arg2, ...);

Мне даже wo на without не пришлось менять.

  1. В паскале есть with, в лиспе with-slots.

Ну так придётся в каждом методе городить конструкцию с этим with.

В Java объект в куче удалится сборщиком мусора. В си не удалится. К ООП это не имеет отношения, конечно. Ранее обсуждался пример явно из C++. Мои рассуждения касались его.

  1. А как можно сделать класс без указателя

Да. Объект класса можно разместить на стеке. И указатель не нужен. alloca возвращает указатель. И нам нужен этот указатель для других «методов». С ним мы не уходим от указателей, уходим от кучи.

Это всё мелочи, конечно. Вполне допускаю, что если собрать синтаксический сахар из разных языков, то можно создать язык без поддержки ООП, на котором такое «ручное» создание классов будет лаконичнее, чем в C++, например. Говорят, на Форте можно что-то типа ООП сделать. Вполне вероятно, что будет очень лаконичность. Только кому такой ООП на Форте нужен, кроме гиков? Насколько им будет комфортно пользоваться?

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

Если она не иммутабельная, конечно.

Это я не совсем понимаю. Если у нас простая структура, типа Point или Color, содержащая минимальный набор примитивных данных, то играйтесь как хотите. А если в структуре куча вложенных структур, массивов, списков, словарей и т.д.?

Давайте рассмотрим какой-нибудь реальный объект, типа окошка GUI, юнита в игре, и т.д. И вот мы хотим перекрасить окошко. Что мы делаем? Копируем старое окошко, как-то прямо в конструкторе поменяв цвет? Ну вот у нас будет два окошка. Старое куда девать? Какой сценарий?

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

Это я не совсем понимаю

Тут тебе помогут https://clojure.org/about/functional_programming#_immutable_data_structures

вот у нас будет два окошка. Старое куда девать?

Выбросить. Зачем тебе старый хлам?

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

Тут тебе помогут

Играются простейшими контейнерами. Сложных структур не увидел.

Выбросить.

Неэффективно как-то. Заполнилась пепельница - меняем целиком автомобиль. Понятно, что в многопотоке такое пересоздание структур целиком может помочь. Но и тут удобнее работать с изменяемой копией, если надо внести несколько изменений. В одном потоке эта иммутабельность непонятно зачем нужна.

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

Играются простейшими контейнерами. Сложных структур не увидел.

Всё точно так же, как и с простыми.

Неэффективно как-то. Заполнилась пепельница - меняем целиком автомобиль

Не обязательно целиком — можно заменить только ту часть, что требует замены.

Nervous ★★★★★
()
Ответ на: комментарий от Kogrom
  1. Согласен. Несколько байт можно выгадать.

  2. Только там, где много работы с полями класса. Зато можно в локальное пространство имён несколько структур запихнуть (сделать как бы метод двух аргументов).

  3. В лиспе тоже удалится сборщиком мусора. И на удаление в современных лиспах можно прикрепить финализатор. В си удалится, если это gcc и использован cleanup.

  4. Когда мы создаём объект на стеке, имя объекта всё равно хранит указатель. Если указатель неприемлем по религиозным причинам и есть только Си, можно сделать

char obj[MYSTRUCT_SIZE];
init_mystruct(obj);

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

Вполне допускаю, что если собрать синтаксический сахар из разных языков, то можно создать язык без поддержки ООП

Есть реальные языки, где ООП излишен. Haskell: классы типов позволяют обеспечить даже бо́льшую лаконичность, чем ООП. Scheme: динамичность позволяет делать полиморфные функции для произвольных типов.

И если использовать ООП, то лучше в стиле лиспа: когда методы не являются частью класса, а являются обобщёнными функциями. Тогда получаем достоинства ООП (диспетчеризация по классу), причём диспетчеризацию можно делать по любому аргументу. И при этом не приходится заранее пытаться угадать архитектуру: появилось действие, сделали функцию; понадобились варианты по классу аргумента — преобразовали в обобщённую функцию. Для пользователя функции вообще ничего не меняется.

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

Мне в подходе ООП не нравится именно то, что на самом раннем этапе надо выбрать, к какому классу отнести метод. Причём, если выбрал неправильно, то цена переделки очень высока.

А в случае типизированных языков ещё и то, что надо заранее выбрать типы всех аргументов. Например, в Java функция не может принимать String, StringBuilder или StringBuffer, несмотря на то, что и всё это — строка. И если после написания крупной программы под нагрузочным тестированием выясняется, что надо заменить String на StringBuilder, то появляется куча мартышкиного труда.

А в лиспе я только меняю (declare (type ...)).

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

И если использовать ООП, то лучше в стиле лиспа: когда методы не являются частью класса, а являются обобщёнными функциями.

Вроде бы тут гибкость в обмен на читаемость. GOTO тоже даёт гибкость, но от него почти везде ушли. Когда методы отдельно от класса, то структура страдает.

Кроме того, гибкость интерпретируемых языков не бесплатна. Обычно быстродействие страдает.

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

Например, в Java функция не может принимать String, StringBuilder или StringBuffer, несмотря на то, что и всё это — строка.

сделай, чтобы все три класса удовлетворяли одному прототипу, нужному в данной функции.

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

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

заменить String на StringBuilder, то появляется куча мартышкиного труда.

А в лиспе я только меняю (declare (type …)).

и весь мартышкин труд делается лиспом в рантайме. но в первом случае код прошел контроль типов, и более верифицирован, а в случае с лиспом - возьмет да и откажется работать.

alysnix ★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)