Здравствуйте, IT, Вы писали:
IT>>Чем это отличается от:
Компилироваться будет быстрее. Но ты мне можешь возразить, что компиляцию можно оптимизировать.
Получается, что я предложил средства. Но того-же результата можно добится другими средствами.
Вообще мне кажется, что за последнее время обостряются споры о средствах, при этом языки, библиотеки и среды разработки становятся всё более схожи друг с другом по возможностям.
Очевидно, что мы приближаемся (кто на практике, а кто в воображении) к идеальному средству, но разными путями.
Здравствуйте, WoldemaR, Вы писали:
WR>Распространённая проблема: Надо залезть в исходник библиотеки и поправить/расширить функциональность объектов некоторого класса. WR>Грязный хак: (Осторожно, маскируется под нормальное решение благодаря общеупотребительности) — WR> Создать свой класс, производный от библиотечного и перегрузить (исправить) нужные методы.
Я бы не назвал это грязным хаком.
По-моему это нормально. Собственно смысл наследования в этом и заключается (в расширении функциональности).
WR>А теперь я заставлю сторонников этой "технологии" раскаятся в содеянном! WR>Посмотрим, на что обречён разработчик:
WR> WR>1) Комбинаторный взрыв вариантов обходных "решений".
Если грамотно применять, совершенно не обязательно.
WR>2) Правка и предусматривание фабричных функций создания экземпляров класса.
Если тебе нужно полиморфное поведение (т.е. и старое и новое), боюсь этого не избежать.
WR>3) Дублирование кода при копировании и модификации метода.
Если ты расширяешь функциональность — то небольшое, в основном в описании сигнатуры метода,
а так вызываешь соотв. метод базового класса.
Для этого даже термин есть — "нормальное наследование".
Если меняешь — ну так все равно придется писать код, реализующий эту функциональность.
А еще от дублирования кода могут помочь mixin ы,
но пока я их видел только в D.
Также можно это делать средствами множественнного наследования (но у тебя, как я понимаю, речь не о C++).
WR>Весёлая "игра", не правда ли? Могу предложить сделать её веселей с помощью ещё более грязных хаков (фич): WR>[list=1] WR>1) Динамически менять версию класса объекта подменой таблицы виртуальных функций и переаллокацией. WR>2) Помечать любой функциональный блок атрибутом версии. WR>3) Хранить все версии методов. WR>4) Хранить каждый метод в самостоятельной dll (сборке). (Напрямую к делу не относится, но очень вкусно). WR>
Вот это уже извраты.
WR>Есть ли более изящные решения?
Можешь попробовать паттерн "Декоратор".
Здравствуйте, WoldemaR, Вы писали:
WR>Распространённая проблема: Надо залезть в исходник библиотеки и поправить/расширить функциональность объектов некоторого класса. WR>Грязный хак: (Осторожно, маскируется под нормальное решение благодаря общеупотребительности) — WR> Создать свой класс, производный от библиотечного и перегрузить (исправить) нужные методы.
Я бы не назвал это грязным хаком.
По-моему это нормально. Собственно смысл наследования в этом и заключается (в расширении функциональности).
Если поправить — да, это немного другое.
Если откровеннный баг и библиотека своя — править сам код, при этом обложить юниттестами чтобы по возможности ничего не поломать.
WR>А теперь я заставлю сторонников этой "технологии" раскаятся в содеянном! WR>Посмотрим, на что обречён разработчик:
WR> WR>1) Комбинаторный взрыв вариантов обходных "решений".
Если грамотно применять, совершенно не обязательно.
WR>2) Правка и предусматривание фабричных функций создания экземпляров класса.
Если тебе нужно полиморфное поведение (т.е. и старое и новое), боюсь этого не избежать.
WR>3) Дублирование кода при копировании и модификации метода.
Если ты расширяешь функциональность — то небольшое, в основном в описании сигнатуры метода,
а так вызываешь соотв. метод базового класса.
Для этого даже термин есть — "нормальное наследование".
Если меняешь — ну так все равно придется писать код, реализующий эту функциональность.
А еще от дублирования кода могут помочь mixin ы,
но пока я их видел только в D.
Также можно это делать средствами множественнного наследования (но у тебя, как я понимаю, речь не о C++).
WR>Весёлая "игра", не правда ли? Могу предложить сделать её веселей с помощью ещё более грязных хаков (фич): WR>[list=1] WR>1) Динамически менять версию класса объекта подменой таблицы виртуальных функций и переаллокацией. WR>2) Помечать любой функциональный блок атрибутом версии. WR>3) Хранить все версии методов. WR>4) Хранить каждый метод в самостоятельной dll (сборке). (Напрямую к делу не относится, но очень вкусно). WR>
Вот это уже извраты. А если блоки помечать атрибутом версии — будет DLL hell.
WR>Есть ли более изящные решения?
Можешь попробовать паттерн "Декоратор".
Эта задача, не является актуальной для всех программистов, но некоторым она постоянно доставляет немало хлопот. Особенно тем, кто активно работает с библиотеками сторонных разработчиков.
А наследование — это трюк, который иногда применяется не по назначению.
Здравствуйте, WoldemaR, Вы писали:
WR>Здравствуйте, ArhAngelVezel, Вы писали:
AAV>>String.prototype.indexOf = function(c) AAV>>{ AAV>> return this.lastIndexOf(c) AAV>>}
WR>Немного похоже, но не то.
WR>Наверное надо показать синтаксис чтобы довести человека до оргазма?
Ты это случаем условную компиляцию не изобрел?
Кстати в D это вполне прилично выглядит:
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, WoldemaR, Вы писали:
WR>>Распространённая проблема: Надо залезть в исходник библиотеки и поправить/расширить функциональность объектов некоторого класса. WR>>Грязный хак: (Осторожно, маскируется под нормальное решение благодаря общеупотребительности) — WR>> Создать свой класс, производный от библиотечного и перегрузить (исправить) нужные методы.
IT>Алтернативы?
Конечно же разумная финализация и миксины.
Здравствуйте, IT, Вы писали:
IT>>>Алтернативы? iZEN>>Конечно же разумная финализация и миксины. IT>А это как нам поможет в столь трудном деле?
Финальность предотвращает наследование.
Миксины обеспечивают наращивание функциональности и специализацию.
Иерархия получается узкой "сверху" и потенциально сверх-широкой "вниз". При этом не будет накладных расходов на полиморфные вызовы и виртуальные таблицы.
Здравствуйте, iZEN, Вы писали:
IT>>А это как нам поможет в столь трудном деле? ZEN>Финальность предотвращает наследование. ZEN>Миксины обеспечивают наращивание функциональности и специализацию. ZEN>Иерархия получается узкой "сверху" и потенциально сверх-широкой "вниз". При этом не будет накладных расходов на полиморфные вызовы и виртуальные таблицы.
Т.е. вместо того, что бы, например, унаследовать свою кнопку от стандартной и перекрыть у неё один метод, мы создаём новый объект и реализуем все без исключения методы как базовой кнопки, так и класса контрола, от которого она унаследована (реализует функциональность указанным тобой способом). Так?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, iZEN, Вы писали:
IT>>>А это как нам поможет в столь трудном деле? iZEN>>Финальность предотвращает наследование. iZEN>>Миксины обеспечивают наращивание функциональности и специализацию. iZEN>>Иерархия получается узкой "сверху" и потенциально сверх-широкой "вниз". При этом не будет накладных расходов на полиморфные вызовы и виртуальные таблицы.
IT>Т.е. вместо того, что бы, например, унаследовать свою кнопку от стандартной и перекрыть у неё один метод, мы создаём новый объект и реализуем все без исключения методы как базовой кнопки, так и класса контрола, от которого она унаследована (реализует функциональность указанным тобой способом). Так?
Как же ты реализуешь, если методы финальные и нельзя перекрыть в наследниках? Это ты как раз описал случай использования чистого ООП, а не миксинов.
Я об обратном. Базовый класс реализует достаточно полное множество методов и представляет собой каркас для подстройки индивидуального поведения с помощью "добавок" — миксинов. Часть методов может быть финальными, совсем небольшая — абстрактными и/или перекрываемыми в потомках.
Иерархия будет расти не в глубину, как в классическом ООП (вспомните Delphi VCL), но быстро приходить к специализированным контролам в наследниках, к которым может быть "примешан" код, отвечающий за специфику применения. То есть очень короткая ветка из минимум двух классов, один из которых библиотечный, может обеспечить ту самую специализацию, к которой стремиться в конечном итоге любая длинная ветка наследовния в ООП.
И, конечно, божеупасивас делать супернавороченный класс "Component" с тремя десятками-сотней методов, чтобы в потомке перекрыть только два-три метода.
Здравствуйте, iZEN, Вы писали:
IT>>Т.е. вместо того, что бы, например, унаследовать свою кнопку от стандартной и перекрыть у неё один метод, мы создаём новый объект и реализуем все без исключения методы как базовой кнопки, так и класса контрола, от которого она унаследована (реализует функциональность указанным тобой способом). Так? ZEN>Как же ты реализуешь, если методы финальные и нельзя перекрыть в наследниках? Это ты как раз описал случай использования чистого ООП, а не миксинов.
Я же там специально для тебя написал "создаём новый объект".
ZEN>Я об обратном. Базовый класс реализует достаточно полное множество методов и представляет собой каркас для подстройки индивидуального поведения с помощью "добавок" — миксинов. Часть методов может быть финальными, совсем небольшая — абстрактными и/или перекрываемыми в потомках.
Т.е. всё таки виртуальные методы у нас присутствуют? Если так, то говорить о "совсем небольшая" или "совсе большая" просто неуместно. Либо виртуальные методы зло и их нет, либо они есть и с этим надо смириться
ZEN>Иерархия будет расти не в глубину, как в классическом ООП (вспомните Delphi VCL), но быстро приходить к специализированным контролам в наследниках, к которым может быть "примешан" код, отвечающий за специфику применения. То есть очень короткая ветка из минимум двух классов, один из которых библиотечный, может обеспечить ту самую специализацию, к которой стремиться в конечном итоге любая длинная ветка наследовния в ООП.
Я в этом сомневаюсь. Всё закончится тем, что излишнее увлечение виртуальными методами перерастёт в излишнее увлечение миксинами.
ZEN>И, конечно, божеупасивас делать супернавороченный класс "Component" с тремя десятками-сотней методов, чтобы в потомке перекрыть только два-три метода.
Точно такой же Component можно и намиксинить. Виртуальные методы тут совершенно ни при чём.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.