Делегирование (объектно-ориентированное программирование) - Delegation (object-oriented programming)
В объектно-ориентированном программировании , делегирование относится к оценке члена ( свойство или метод ) одного объекта (приемник) в контексте другого исходного объекта (отправитель). Делегирование может быть выполнено явно, путем передачи объекта-отправителя объекту-получателю, что может быть выполнено на любом объектно-ориентированном языке ; или неявно, правилами поиска членов языка, который требует языковой поддержки для функции. Неявное делегирование - это фундаментальный метод повторного использования поведения в программировании на основе прототипов , соответствующий наследованию в программировании на основе классов . Самыми известными языками, поддерживающими делегирование на уровне языка, являются Self , который включает в себя понятие делегирования через понятие изменяемых родительских слотов , которые используются при поиске метода при самостоятельных вызовах, и JavaScript ; см. делегирование JavaScript .
Термин делегирование также широко используется для различных других отношений между объектами; подробнее см. делегирование (программирование) . Часто путаемые концепции просто используют другой объект, более точно называемый консультацией или агрегированием ; и оценка члена на одном объекте путем оценки соответствующего члена на другом объекте, особенно в контексте принимающего объекта, что более точно называется пересылкой (когда объект-оболочка не передает себя завернутому объекту). Шаблон делегации является шаблоном проектирования программного обеспечения для реализации делегирования, хотя этот термин также используется свободно для консультаций или передачи.
Обзор
Это ощущение делегирования как функции языка программирования, использующей правила поиска методов для диспетчеризации так называемых самовызовов, было определено Либерманом в его статье 1986 года «Использование прототипов для реализации общего поведения в объектно-ориентированных системах».
Делегирование зависит от динамического связывания , поскольку требует, чтобы вызов данного метода мог вызывать различные сегменты кода во время выполнения. Он используется в macOS (и ее предшественнице NeXTStep ) как средство настройки поведения компонентов программы. Он позволяет реализовать такие реализации, как использование одного класса, предоставляемого ОС, для управления окнами, поскольку класс принимает делегат, зависящий от программы, и может при необходимости переопределять поведение по умолчанию. Например, когда пользователь щелкает поле закрытия, диспетчер окон отправляет делегату вызов windowShouldClose:, и делегат может отложить закрытие окна, если есть несохраненные данные, представленные содержимым окна.
Делегирование можно охарактеризовать (и отличить от пересылки ) как позднее связывание себя :
... сообщения, отправленные в переменную
self
(илиthis
) в родительском элементе, «вернутся» к объекту, который изначально получил сообщение.
То есть self
в определении метода в принимающем объекте статически не привязан к этому объекту во время определения (например, во время компиляции или когда функция прикреплена к объекту), а во время оценки он привязан к исходному объект.
Утверждалось, что в некоторых случаях делегирование может быть предпочтительнее наследования, чтобы сделать программный код более читаемым и понятным. Несмотря на то, что явное делегирование довольно широко распространено, относительно немногие основные языки программирования реализуют делегирование в качестве модели, альтернативной наследованию. Точная связь между делегированием и наследованием сложна; некоторые авторы считают их эквивалентными, либо одно - частным случаем другого.
Языковая поддержка для делегирования
В языках, поддерживающих делегирование через правила поиска методов, диспетчеризация методов определяется так, как она определена для виртуальных методов в наследовании: это всегда наиболее конкретный метод, который выбирается во время поиска метода. Следовательно, именно исходный объект-получатель является началом поиска метода, даже если он передал управление какому-то другому объекту (через ссылку делегирования, а не ссылку на объект).
Преимущество делегирования в том, что оно может происходить во время выполнения и влиять только на подмножество сущностей определенного типа и даже может быть удалено во время выполнения. Наследование, напротив, обычно нацелено на тип, а не на экземпляры, и ограничивается временем компиляции. С другой стороны, наследование может быть статически проверено типом, в то время как делегирование, как правило, невозможно без дженериков (хотя ограниченная версия делегирования может быть статически типобезопасной). Делегирование можно назвать «наследованием во время выполнения для определенных объектов».
Вот пример псевдокода на языке, подобном C # / Java :
class A {
void foo() {
// "this" also known under the names "current", "me" and "self" in other languages
this.bar();
}
void bar() {
print("a.bar");
}
};
class B {
private delegate A a; // delegation link
public B(A a) {
this.a = a;
}
void foo() {
a.foo(); // call foo() on the a-instance
}
void bar() {
print("b.bar");
}
};
a = new A();
b = new B(a); // establish delegation between two objects
Вызов b.foo()
приведет к печати a.bar , поскольку он this
относится к исходному объекту-получателю b
в контексте a
. Возникающая в результате двусмысленность this
называется объектной шизофренией .
При this
преобразовании неявного параметра в явный, вызов (в B
, с a
делегатом) a.foo()
преобразуется в A.foo(b)
, используя тип a
для разрешения метода, но объект делегирования b
для this
аргумента.
При использовании наследования аналогичный код (с использованием заглавных букв, чтобы подчеркнуть, что разрешение основано на классах, а не на объектах):
class A {
void foo() {
this.bar();
}
void bar() {
print("A.bar");
}
};
class B extends A {
public B() {}
void foo() {
super.foo(); // call foo() of the superclass (A)
}
void bar() {
print("B.bar");
}
};
b = new B();
Вызов b.foo()
приведет к B.bar . В этом случае this
однозначно: существует единственный объект ,, b
и this.bar()
разрешается в метод подкласса.
Языки программирования в целом не поддерживают эту необычную форму делегирования как языковую концепцию, но есть несколько исключений.
Двойное наследование
Если язык поддерживает как делегирование, так и наследование, можно выполнить двойное наследование , используя оба механизма одновременно, как в
class C extends A {
delegationlink D d;
}
Это требует дополнительных правил для поиска методов, поскольку теперь потенциально есть два метода, которые можно обозначить как наиболее специфичные (из-за двух путей поиска).
Связанные области
Делегирование можно описать как механизм низкого уровня для совместного использования кода и данных между объектами. Таким образом, он закладывает основу для других языковых конструкций. В частности, ролевые языки программирования использовали делегирование, но особенно старые фактически использовали агрегацию , утверждая, что используют делегирование. Это не следует рассматривать как обман, это просто множественное определение того, что означает делегирование (как описано выше).
Совсем недавно была проделана работа по распределению делегирования, поэтому, например, клиенты поисковой системы (поиск дешевых гостиничных номеров) могут использовать общий объект, используя делегирование, чтобы делиться лучшими совпадениями и общей функциональностью многократного использования.
Делегация также была предложена Эрнстом и Лоренцем для решения рекомендаций по аспектно-ориентированному программированию в 2003 году.
Смотрите также
- Шаблон делегирования
- Шаблон адаптера
- Крючок
- Продолжение
- Наследование реализации
- Семантика наследования
- Шизофрения (объектно-ориентированное программирование)
- Виртуальное наследование
- Функция обертки
Различать:
- Делегат (CLI)
- Делегирование (программирование)
- Агрегация объектов
- Пересылка (объектно-ориентированное программирование)
Примечания
использованная литература
- Либерман, Генри (1986). «Использование прототипов объектов для реализации общего поведения в объектно-ориентированных системах» . Материалы конференций по системам, языкам и приложениям объектно-ориентированного программирования . Уведомления ACM SIGPLAN . 21 . Портленд. С. 214–223. CiteSeerX 10.1.1.48.69 . DOI : 10.1145 / 960112.28718 .
- Линн Андреа Штайн, Генри Либерман, Дэвид Ангар: общий взгляд на обмен: Орландоский договор . В: Вон Ким, Фредерик Х. Лочовски (ред.): Объектно-ориентированные концепции, базы данных и приложения ACM Press, Нью-Йорк, 1989, гл. 3, pp. 31–48 ISBN 0-201-14410-7 (на сайте Citeseer )
- Гамма, Эрих ; Хелм, Ричард ; Джонсон, Ральф ; Влиссидес, Джон (1995). Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон-Уэсли . ISBN 978-0-201-63361-0.
- Маленфант Дж .: О семантическом разнообразии языков программирования, основанных на делегировании, Труды OOPSLA95, Нью-Йорк: ACM 1995, стр. 215–230.
- Бек, Кент (1997). Шаблоны передовой практики Smalltalk . Прентис Холл. ISBN 978-0134769042.
- Каспер Билстед Граверсен: Природа ролей --- Таксономический анализ ролей как языковой конструкции. Кандидат наук. Диссертация 2006 г. (Интернет в ИТ-университете Копенгагена )
внешние ссылки
- Новый способ реализации делегата на C ++
- Быстрые делегаты в C ++
- PerfectJPattern Open Source Project , предоставляет многоразовую реализацию делегатов на Java