В языках программирования обычно наследование делается просто указанием нового и старого класса.
Этого достаточно, чтобы новый класс обладал методами старого класса.
class NewClass: OldClass
Делегирование очень часто является более подходящим (правильным) паттерном,
но в обычных языка делегирование становится многословным. Приходится явно описывать каждый делегируемый метод
Здравствуйте, Буравчик, Вы писали:
Б>Вопрос. Есть ли языки, которые позволяют применить делегирование также элегантно (немногословно), как и наследование?
Здравствуйте, Буравчик, Вы писали:
Б>Вопрос. Есть ли языки, которые позволяют применить делегирование также элегантно (немногословно), как и наследование?
Здравствуйте, Jack128, Вы писали:
Б>>Вопрос. Есть ли языки, которые позволяют применить делегирование также элегантно (немногословно), как и наследование? J>Delphi, kotlin
Интересно... А на примерах покажете?
Нет такого преступления, на которое не пошло бы суверенное родоплеменное быдло ради продления своего бессмысленного рода и распространения своего бессмысленного генома.
class Example {
var p: String by Delegate()
}
...
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return"$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name} in $thisRef.'")
}
...
val e = Example()
println(e.p)
Example@33a17727, thank you for delegating ‘p’ to me!
Здравствуйте, Jack128, Вы писали:
J>Здравствуйте, Буравчик, Вы писали:
Б>>Вопрос. Есть ли языки, которые позволяют применить делегирование также элегантно (немногословно), как и наследование?
J>Delphi, kotlin
Здравствуйте, Буравчик, Вы писали:
Б>Вопрос. Есть ли языки, которые позволяют применить делегирование также элегантно (немногословно), как и наследование?
Если понимать вопрос буквально, то я бы добавил яваскрипт
Здравствуйте, Буравчик, Вы писали:
Б>Делегирование очень часто является более подходящим (правильным) паттерном, но в обычных языка делегирование становится многословным. Приходится явно описывать каждый делегируемый метод Б>
Не обязательно. Используя кодогенерацию можно реализовать более изящное решение. Например, в Perl с помощью фреймворков Moo(se) это будет выглядеть так (все нужные методы будут сгенерированы.):
package NewClass;
has obj => (
is => 'rw',
isa => InstanceOf[OldClass],
handles => [qw(method1 method2 method3)],
);
struct Foo
{
int baz = 4;
int get() { return 7; }
}
class Bar
{
Foo foo;
alias foo this;
}
void main()
{
auto bar = new Bar;
int i = bar.baz; // i == 4
i = bar.get(); // i == 7
}
Здравствуйте, Буравчик, Вы писали:
Б>Вопрос. Есть ли языки, которые позволяют применить делегирование также элегантно (немногословно), как и наследование?
Go.
type Parent struct {
a, b int
}
type Child {
Parent
c, f bool
}
Parent является в структуре Child анонимным полем.
Child наследует содержимое Parent'а и все его методы, если только не оверриайдит их собственными.
Здравствуйте, 0BD11A0D, Вы писали:
BDA>Здравствуйте, Буравчик, Вы писали:
Б>>Делегирование очень часто является более подходящим (правильным) паттерном,
BDA>Это в каких же?
BDA>С моей точки зрения, делегирование по сути своей — весьма спорный паттерн и поэтому очень хорошо, что прописывать его надо явно.
Если воспринимать его просто как сахар, то вполне нормально (и в том же С++ элементарно реализуется на макросах, кстати)
Здравствуйте, AlexRK, Вы писали:
BDA>>С моей точки зрения, делегирование по сути своей — весьма спорный паттерн ARK>А в чем именно он спорный? Мне всегда казалось, что в правильно реализованном делегировании нет мест, где можно случайно наломать дров.
А вы приведите хоть один пример с правильным делегированием, его и разберем.
Здравствуйте, 0BD11A0D, Вы писали:
BDA>>>С моей точки зрения, делегирование по сути своей — весьма спорный паттерн ARK>>А в чем именно он спорный? Мне всегда казалось, что в правильно реализованном делегировании нет мест, где можно случайно наломать дров.
BDA>А вы приведите хоть один пример с правильным делегированием, его и разберем.
А без моего примера не можете пояснить свои слова про спорный паттерн?
Здравствуйте, AlexRK, Вы писали:
ARK>А без моего примера не можете пояснить свои слова про спорный паттерн?
Могу написать общие соображения. Они сводятся к тому, что такой код мало соотносится с жизнью, слишком абстрактен, а поэтому он читается намного хуже.
И как, полегчало? Не думаю.
Жизнь меня научила тому, что надо сразу переходить к примерам. Допустим, вы бы хотели возложить бремя придумывания примеров на меня. Есть одна проблемка: примеры чего, мне, человеку, которому паттерн кажется спорным, следует привести? Того, что он спорен? А вы на это скажете, что это мои примеры плохие (но есть хорошие).
Вот это все я мысленно опустил и предложил: давайте вы сразу приведете пример хорошего кода с делегированием. Где делегирование улучшает читаемость или мешает совершению ошибок. (Другие критерии я не думаю, что есть смысл рассматривать, но готов, если убедительно покажете). А я перепишу его без делегирования или признаю, что оно уместно. Так мы сможем быстро разобрать все случаи. К игре приглашаются все желающие.
ARK>Ну ок, вот выше был пример: http://rsdn.ru/forum/philosophy/6393576.1
Здравствуйте, 0BD11A0D, Вы писали:
BDA>Вот это все я мысленно опустил и предложил: давайте вы сразу приведете пример хорошего кода с делегированием. Где делегирование улучшает читаемость или мешает совершению ошибок. (Другие критерии я не думаю, что есть смысл рассматривать, но готов, если убедительно покажете). А я перепишу его без делегирования или признаю, что оно уместно. Так мы сможем быстро разобрать все случаи. К игре приглашаются все желающие.
Возьмём старый добрый COM. И его ярчайших представителей — VB, Delphi, C++/ATL.
В васике наследования вообще не было. Так что переписывать на нём без делегирования просто не получится.
Компонентная модель вообще предполагает, что кастомизация поведения объектов происходит только через предоставление интерфейсов друг другу, а делегирование — просто немножко сахара над этим.
Чем делегирование лучше наследования:
Наследование создаёт россыпь интерфейсов толщиной в одну функцию (поскольку каждую функцию можно переопределить).
И эти интерфейсы доступны как наружу, так и внутри реализации — интерфейсы наследников к предку (механизм, который эксплуатируется в паттерне "шаблонный метод", например).
Для каждого интерфейса мысленно прописывается контракт. А если несколько функций выступают в связке, то этот контракт расползается, его легче нарушить.
При делегировании каждый класс отвечает за соблюдение своей части контракта.
Чем делегирование хуже: оно дороже по памяти, по скорости, ну и по писанине тоже.
Здравствуйте, vsb, Вы писали:
К>>Чем делегирование хуже: оно дороже по памяти, по скорости, ну и по писанине тоже. vsb>Речь о ручном делегировании? Если язык поддерживает делегирование на уровне синтаксиса, почему оно дороже?
Синтаксис уменьшает писанину, но ненамного. В ATL делегирование интерфейса агрегату (и, одновременно, предоставление ему своих интерфейсов) займёт ровно одну строчку.
Плюс пару строк обвязки в коклассах главного объекта и агрегата, — но они так и этак добавятся.
А память и скорость — это почти неизбежная расплата.
Только если синтаксическими макросами сделать облако связанных объектов с минимальной косвенностью вызовов (немерле, шаблоны C++ — правда, именно шаблоны в нынешней редакции не могут сделать это бесплатно и изящно).
Хотя, если C++, препроцессор плюс CRTP, наверно, можно сделать инфраструктуру...
Здравствуйте, Кодт, Вы писали:
BDA>>Вот это все я мысленно опустил и предложил: давайте вы сразу приведете пример хорошего кода с делегированием. Где делегирование улучшает читаемость или мешает совершению ошибок. (Другие критерии я не думаю, что есть смысл рассматривать, но готов, если убедительно покажете). А я перепишу его без делегирования или признаю, что оно уместно. Так мы сможем быстро разобрать все случаи. К игре приглашаются все желающие.
К>Возьмём старый добрый COM. И его ярчайших представителей — VB, Delphi, C++/ATL. К>В васике наследования вообще не было. Так что переписывать на нём без делегирования просто не получится. К>Компонентная модель вообще предполагает, что кастомизация поведения объектов происходит только через предоставление интерфейсов друг другу, а делегирование — просто немножко сахара над этим.
Ну хорошо: если его нечем заменить (из языка убраны другие средства), тогда, конечно.
К>Чем делегирование лучше наследования: К>Наследование создаёт россыпь интерфейсов толщиной в одну функцию (поскольку каждую функцию можно переопределить). К>И эти интерфейсы доступны как наружу, так и внутри реализации — интерфейсы наследников к предку (механизм, который эксплуатируется в паттерне "шаблонный метод", например). К>Для каждого интерфейса мысленно прописывается контракт. А если несколько функций выступают в связке, то этот контракт расползается, его легче нарушить. К>При делегировании каждый класс отвечает за соблюдение своей части контракта.
К>Чем делегирование хуже: оно дороже по памяти, по скорости, ну и по писанине тоже.
А вот это хотелось бы в виде кода, поскольку там вероятны какие-то проблемы с декомпозицией.