LINUX.ORG.RU

Когда использовать ООП?

 


0

3

Доброго времени суток, господа!

Собственно, сабж. Но сразу оговорюсь, что под ООП в данном случае подразумеваю то самое махровое ООП из пропаганды маркетолухов, Java, C# и т.д.

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

Где находится та грань, когда нужно использовать ООП? Вот взять те же игры, многие легендарные игры написаны и без использования ООП. Так как же поступать? Как применять инструменты правильно?


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

это в «стиле с++» записан класс, имеющий дефолтный конструктор и операцию cons, возвращающую ссылку на обьект того же класса. Суть операции не раскрывается, но она не так и важна.

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

вот и вопрос. почему у вас определение считается рекурсивным, а определение в стиле с++ - нет

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

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

Кем не считается?

почему у вас определение считается рекурсивным

Потому что тип определён через самого себя. Это, вероятно, написано в любом учебнике по алгоритмам и структурам данных, на любом ЯП.

type List =
  record
    head: Integer;
    tail: ^List;
  end;
struct list {
	int   head;
	list* tail;
};
korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Потому что тип определён через самого себя.

тип не может быть определенным через самого себя. пример

struct a {
  a _field;
}

такое невозможно.

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

struct a {
  a& _field;
}

или вам без разницы?

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

или вам без разницы?

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

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

а цикл например в наследовании является непреодолимым изъяном в иерархии. такого просто не может быть.

Да ладно?! Неужели не сталкивались с

class MyClass : public Something<MyClass> {
   …
};

?

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

Для определения рекурсивности определения типа — без разницы. Использование ссылки / указателя / альтернативных конструкторов (тэгов) / ссылочной семантики для типов необходимо для конечности этой самой рекурсии, но рекурсию не отменяет.

там нет рекурсии. пример из с++

class A;
A* some_ptr0 = nullptr;
A* some_ptr1 = some_ptr0;

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

найдите тут рекурсию.

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

вот ваш пример. в нем, как только появилось имя list, возник автоматически тип - *list, который используется в поле tail. там нет рекурсий. там типы, определяемые автоматом.

struct list { <--- вот тут компилятор сразу завел тип list* и list&
	int   head;
	list* tail;
};
alysnix ★★★
()
Ответ на: комментарий от bugfixer

Неужели не сталкивались с

это отношение зависимости, а не наследования. MyClass сам себя тут не наследует, ибо тогда компилятор не смог бы даже рассчитать размер получающегося класса MyClass. Скорее всего там в базе используются указатели на MyClass, как раз в том смысле о котором вот только что сказал. указатели и ссылки это не вполне пользовательские типы, а скорее «автоматические типы» или «способы доступа» к значению.

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

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

найдите тут рекурсию.

facepalm. К чему этот пример? Конечно, он не имеет никакого отношения к рекурсии. Вы определение рекурсии прочитайте, что ли. В поиск вбейте «рекурсивные структуры данных», «рекурсивные типы данных», «recursive data types».

возник автоматически тип - *list

И? list определён через *list, *list определён через list. Круг замкнулся.

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

И? list определён через *list, *list определён через list. Круг замкнулся.

нет. указатель вообще-то «псевдотип», или «тип-метод_доступа», его не нужно определять явно.

то есть

T* variable;

не требует определения T, а только объявления, что он вообще существует.

то есть в данном случае *list не «определен» через list, а просто является типом-атрибутом(типом спутником, типом-доступом к значению) list. соответственно вы можете определять list в любых терминах, в том числе и list *, и это не будет является рекурсией.

в компиляторе вообще нет никакой «рекурсивности» по этому поводу. не ну не знаю как в ваших хаскелях и проч. но в простых таких язычках, типа си, с++, шарпов, яв. там просто тип-указатель рождается автоматом при попытке обьявить некий тип.

разговор вообще-то был о наследовании. и что якобы «рекурсия» в типе рождает бесконечное наследование… но это вообще в огороде бузина.

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

компилятор при том, что он ничего не знает о «рекурсивности» определения типа и не совершает по этому поводу никаких специфических действий. то есть декларации вида

class B;

class A {
  B* _next; ///тут B обьявлен, и все отлично
}
class A {
  A* _next; ///тут А обьявлен, и все также отлично
}

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

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

Получается, что ООП необходим чуть более чем всегда — хотя на деле он необходим чуть менее, чем никогда. Просто ещё один способ организации вычислений, и не из лучших.

Просто большая часть людей не имеет своего мнения и ретранслирует всё, что услышит. Был прогон, что «OOP is considered harmful», результат – любой может пояснить, что это так.

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

А христиане как-то без этого обходятся. И не страдают.

А они как в ресторане:

Вот это мне нравится, дайте два. Не носить одежду одновременно из шерсти и хлопка? Пожалуй, нет. Наложницы, многоженство, забивание камнями, рабство, геноцид, жертвоприношения? Не сегодня.

anonymous
()

Всему свое место. Если нужно ООП, то его и используют. А если не нужно — пишут в процедурном стиле.

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

anonymous
()