Здравствуйте, LaptevVV, Вы писали:
LVV>Кстати, ровно тот же подход предлагали оберонцы! Наследование интерфейсов, а вместо наследования реализации использовать композицию... :)
Здравствуйте, Privalov, Вы писали:
P>Наследование реализации — зло. P>Наследование реализации ничем не лучше копипасты.
Пример паттерна шаблонный метод на псевдокоде.
// Базовый библиотечный класс.class Base
{
public:
void PerformFixedAlgorithmWithOverridableSubsteps()
{
CheckSomePreconditions();
if (condition1)
PerformSubstep1();
while (condition2)
PerformSubstep2();
}
private:
// Эти методы вызываются, но не определяются в базовом классе.
abstract void PerformSubstep1();
abstract void PerformSubstep2();
}
// Производный пользовательский класс.class Derived
{
private:
// Эти методы определяются, но не вызываются в производном классе.
override void PerformSubstep1() { ... }
override void PerformSubstep2() { ... }
}
// Использование производного пользовательского класса.
Derived d;
d.PerformFixedAlgorithmWithOverridableSubsteps();
Является ли такое наследование реализации злом, и что предлагается вместо него?
Здравствуйте, Privalov, Вы писали:
Ф>>Наследование реализации — вещь полезная, т.к. позволяет экономить усилия. P>Наследование реализации — зло. В одном из проектов было примерно 8 уровней наследования, причем довольно часто оно применялось только за тем, что в наследуемом классе был подходящий метод. [...]
Только не надо ставить всё с ног на голову. В восьмиярусном наследовании, сделанном абы как, сиречь: "только за тем, что в наследуемом классе был подходящий метод" главное зло — не наследование, а это самое "только за тем ...".
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Трололоша, Вы писали:
VD>>В Обероне найден фатальный недостаток? Т>Полагаю классический случай NIH
Кончайте брюзжать, в вузах как раз и полагается делать всё самим, а не гундосить: "Всё уже придумано, надо только пользоваться". Это же здорово — сделать всё самому!
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Философ, Вы писали:
Ф>Наследование реализации — вещь полезная, т.к. позволяет экономить усилия.
У нее слишком много побочных эффектов и она идет в одном флаконе с наследованием интерфейсов.
Ф>Однажды я сначала руками написал около сотни практически не отличающихся наследников (все они определяли ровно два небольших метода, объявленных в базовом классе как абстрактные), а потом, когда надоело писать руками, написал для них генератор. Ф>Сейчас даже не представляю, как всё это могло бы быть сделано без возможности наследовать реализацию.
Ну это ты не представляешь. А вообще можно, к примеру, было передать единственному классу в конструктор 1-2 функции. Если абсолютно одинаковые функции применялись не в одном месте (хотя при сотне вариантов такое, видимо, было редко) — конструктор вынести в статический метод-фабрику.
... << RSDN@Home 1.2.0 alpha 5 rev. 65 on Windows 7 6.1.7601.65536>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Ну это ты не представляешь. А вообще можно, к примеру, было передать единственному классу в конструктор 1-2 функции. Если абсолютно одинаковые функции применялись не в одном месте (хотя при сотне вариантов такое, видимо, было редко) — конструктор вынести в статический метод-фабрику.
Это по сути ручная реализация таблицы виртуальных функций. Эдак вообще никакого наследования или динамического полиморфизма via vtable не надо — знай себе передавай пачки функций в ктор, примерно как делали наши пращуры на Си.
Здравствуйте, Qbit86, Вы писали:
Q>Это по сути ручная реализация таблицы виртуальных функций.
С чего это она ручная? Указатель на функцию ничуть не менее виртуален, нежели виртуальная функция. Если писать меньше надо — какой смысл тащить туда наследование?
Q> Эдак вообще никакого наследования или динамического полиморфизма via vtable не надо — знай себе передавай пачки функций в ктор, примерно как делали наши пращуры на Си.
Или как делают в некоторых функциональных языках сейчас. Наследование интерфейсов нужно далеко не только для того, чтобы сгруппировать пачку функций. Наследование интерфейсов это прежде всего каркас дизайна. И оно вполне допустимо для обрисовывания структуры решения. А вот сотня наследников, отличающихся на 1-2 маленьких функции это крайне фиговый дизайн.
... << RSDN@Home 1.2.0 alpha 5 rev. 65 on Windows 7 6.1.7601.65536>>
Q>Является ли такое наследование реализации злом, и что предлагается вместо него?
Походу, однозначным злом не является. Но это стерильный случай. На практике возможность наследования реализации часто приводит к менее безобидным конструкциям.
Предлагается, на сколько я понимаю, выделить интерфейс сущности, которая делает Q> abstract void PerformSubstep1(); Q> abstract void PerformSubstep2();
и уже ее реализации подсовывать.
> Y>На практике возможность наследования реализации часто приводит к менее безобидным конструкциям. > > Вы наверное хотели написать "В моей практике" ? > > не надо переносить свой опыт на остальных.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Философ, Вы писали:
Ф>>Наследование реализации — вещь полезная, т.к. позволяет экономить усилия.
AVK>Ну это ты не представляешь. А вообще можно, к примеру, было передать единственному классу в конструктор 1-2 функции.
нафига это городить?
если единственная цель — чистота концепции, то это не мой путь.
главное — простота и понятность решения, лёгкость сопровождения.
AVK>Если абсолютно одинаковые функции применялись не в одном месте (хотя при сотне вариантов такое, видимо, было редко)
не понял
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Философ, Вы писали:
AVK>>Ну это ты не представляешь. А вообще можно, к примеру, было передать единственному классу в конструктор 1-2 функции. Ф>нафига это городить?
Городить? Я тебе предлагаю вместо сотни классов сделать один — экономия в размере кода и количестве сущностей будет огромная. Работать со 100 однотипными наследниками весьма некомфортно.
Ф>если единственная цель — чистота концепции, то это не мой путь.
Единственная цель дизайна — сделать написание и поддержание кода максимально дешевым. Все остальное от лукавого.
Ф>главное — простота и понятность решения, лёгкость сопровождения.
Ты считаешь, что 100 классов легче сопровождать, чем один?
AVK>>Если абсолютно одинаковые функции применялись не в одном месте (хотя при сотне вариантов такое, видимо, было редко) Ф>не понял
Что не понял? Если у тебя каждый из сотни классов инстанцируется ровно в одном месте (или в нескольких, но рядом), то проще передавать функции по месту. Если нет — вынести вызов конструктора в статический метод. Архитектура, в которой сотня однотипных классов, каждый из которых создается в разных местах, это вообще что то трудновообразимое. И уж точно это не про "простота и понятность решения, лёгкость сопровождения".
... << RSDN@Home 1.2.0 alpha 5 rev. 65 on Windows 7 6.1.7601.65536>>
Здравствуйте, Геннадий Васильев, Вы писали:
VD>>>В Обероне найден фатальный недостаток? Т>>Полагаю классический случай NIH
ГВ>Кончайте брюзжать, в вузах как раз и полагается делать всё самим, а не гундосить: "Всё уже придумано, надо только пользоваться". Это же здорово — сделать всё самому!
Ну я как бы большой любитель сделать всё сам vs разгребать чужие говны навороты, но тут мне сама цель не понятна. Как обучающий проект с возможным практическим применением — да, но как сразу практический проект — "ну нипанятна же!" (С)
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Философ, Вы писали:
AVK>>>Ну это ты не представляешь. А вообще можно, к примеру, было передать единственному классу в конструктор 1-2 функции. Ф>>нафига это городить?
AVK>Городить? Я тебе предлагаю вместо сотни классов сделать один — экономия в размере кода и количестве сущностей будет огромная. Работать со 100 однотипными наследниками весьма некомфортно.
а с одним(?) чудовищного размера классом просто?
Ф>>если единственная цель — чистота концепции, то это не мой путь.
AVK>Ты считаешь, что 100 классов легче сопровождать, чем один?
пофигу, хоть 100, хоть 1000 — вряд-ли кому придёт в голову править генерируемый код.
а потом, да: если в классе будет 1,0E+03 полей и столько же свойств, то это значительно хуже чем 1,0E+02 классов.
AVK>>>Если абсолютно одинаковые функции применялись не в одном месте (хотя при сотне вариантов такое, видимо, было редко) Ф>>не понял
AVK>Что не понял? Если у тебя каждый из сотни классов инстанцируется ровно в одном месте (или в нескольких, но рядом), то проще передавать функции по месту. Если нет — вынести вызов конструктора в статический метод.
наиболее интересный вопрос здесь: где эти самые "функции" будут находиться, откуда их брать, чтоб в конструктор их передавать?
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Философ, Вы писали:
Ф>а с одним(?) чудовищного размера классом просто?
А зачем один чудовищного размера? Я такого не предлагал.
AVK>>Ты считаешь, что 100 классов легче сопровождать, чем один? Ф>пофигу, хоть 100, хоть 1000 — вряд-ли кому придёт в голову править генерируемый код.
Знаешь, если код можно сгенерировать, то очень часто его можно вообще не генерировать.
Ф>наиболее интересный вопрос здесь: где эти самые "функции" будут находиться, откуда их брать, чтоб в конструктор их передавать?
Я не могу ответить тебе на этот вопрос, потому что не знаю подробностей. Ты спросил, чем заменить наследование, я тебе ответил. А в контексте генерации кода вообще можно без какого либо наследования обходится — дизайн и читабельность генеренного кода не особо важны, если это не публичные контракты.
... << RSDN@Home 1.2.0 alpha 5 rev. 65 on Windows 7 6.1.7601.65536>>
Здравствуйте, LaptevVV, Вы писали:
AVK>>Мое предложение — множественное наследование интерфейсов и отсутствие наследования реализаций. Т.е. классы вообще не наследуются. А для реюза кода придумать способ упрощения агрегации. LVV>Кстати, ровно тот же подход предлагали оберонцы! Наследование интерфейсов, а вместо наследования реализации использовать композицию...
Плюс они предлагали функциональный тип-делегаты, чтобы оно хоть как-то взлетело.
Здравствуйте, LaptevVV, Вы писали:
LVV>3. Хотелось прояснить для себя некоторые вопросы — вот в частности с наследованием. Кроме того, пацан в процессе реализации интерпретатора наткнулся на интересную штуку: оказалось, ссылочную семантику и семантику значений можно реализовать в рамках одного язвка. И появилась возможность одной кнопочкой переключать это дело. Более того, если сделать API, то можно и в процессе интерпретации переключать эту семантику.
Чего? Это же радикально меняет поведение кода.
Единственный случай, когда такое преобразование не скажется на поведении это когда объекты, которым переключают семантику неизменяемые.
Если же они изменяемый то это
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, AndrewVK, Вы писали:
V>>Любое автоматическое делегирование методов агрегату будет делать ровно то же самое. AVK>Не обязательно. Для примера — как думаешь, что порождает большую связность — встроенные в CLR эвенты или IObservable из 4+ фреймворка?
Это смотря как на эвенты подписываться. А то ведь можно и через EventDescriptor.