Делегирование (объектно-ориентированное программирование)
В объектно-ориентированном программировании делегирование относится к оценке члена ( свойства или метода ) одного объекта (получателя) в контексте другого исходного объекта (отправителя). Делегирование можно выполнить явно, передав обязанности объекта-отправителя объекту-получателю, что можно сделать на любом объектно-ориентированном языке ; или неявно, правилами поиска членов языка, который требует языковой поддержки этой функции. Неявное делегирование — это фундаментальный метод повторного использования поведения в программировании на основе прототипов , соответствующий наследованию в программировании на основе классов . Наиболее известными языками, поддерживающими делегирование на уровне языка, являются Self , который включает в себя понятие делегирования посредством понятия изменяемых родительских слотов , которые используются при поиске метода при самовызовах, и JavaScript ; см . делегирование JavaScript .
Термин делегирование также широко используется для обозначения других отношений между объектами; см . делегирование (программирование) подробнее . Понятия, которые часто путают, просто используют другой объект, точнее называемый консультацией или агрегацией ; и оценку члена одного объекта путем оценки соответствующего члена другого объекта, особенно в контексте принимающего объекта, что более точно называется пересылкой (когда объект-оболочка не передает себя обернутому объекту). [1] [2] [а] Шаблон делегирования — это шаблон проектирования программного обеспечения для реализации делегирования, хотя этот термин также широко используется для консультаций или пересылки.
Обзор
[ редактировать ]Это чувство делегирования как особенности языка программирования, использующей правила поиска методов для отправки так называемых самовызовов , было определено Либерманом в его статье 1986 года «Использование прототипных объектов для реализации общего поведения в объектно-ориентированных системах».
Делегирование зависит от динамического связывания , поскольку оно требует, чтобы данный вызов метода мог вызывать различные сегменты кода во время выполнения. [ нужна ссылка ] . Он используется в macOS (и его предшественнике NeXTStep ) как средство настройки поведения программных компонентов. [3] Это позволяет реализовать такие реализации, как использование одного класса, предоставляемого ОС, для управления окнами, поскольку класс принимает делегат, специфичный для программы, и может при необходимости переопределить поведение по умолчанию. Например, когда пользователь щелкает поле закрытия, оконный менеджер отправляет делегату вызов windowShouldClose:, и делегат может отложить закрытие окна, если в содержимом окна есть несохраненные данные.
Делегирование можно охарактеризовать (и отличить от пересылки ) как позднее связывание себя : [4]
... сообщения, отправленные на
self
(илиthis
) в родительской переменной «вернется» к объекту, который первоначально получил сообщение.
То есть self
в определении метода в принимающем объекте статически не привязан к этому объекту во время определения (например, во время компиляции или когда функция присоединена к объекту), а скорее во время оценки он привязан к исходному объекту.
Утверждалось, что в некоторых случаях делегирование может быть предпочтительнее наследования , чтобы сделать программный код более читабельным и понятным. [5] Несмотря на то, что явное делегирование довольно широко распространено, относительно немногие основные языки программирования реализуют делегирование в качестве модели, альтернативной наследованию. Точная связь между делегированием и наследованием сложна; некоторые авторы считают их эквивалентными или одним частным случаем другого. [6]
Языковая поддержка делегирования
[ редактировать ]В языках, которые поддерживают делегирование с помощью правил поиска методов, диспетчеризация методов определяется так же, как она определяется для виртуальных методов при наследовании: во время поиска метода всегда выбирается наиболее конкретный метод. Следовательно, именно исходный объект-получатель является началом поиска метода, даже если он передал управление какому-либо другому объекту (через ссылку делегирования, а не ссылку на объект).
Преимущество делегирования состоит в том, что оно может осуществляться во время выполнения и влиять только на подмножество сущностей определенного типа, а также может быть удалено во время выполнения. Наследование, напротив, обычно нацелено на тип, а не на экземпляры, и ограничивается временем компиляции. С другой стороны, наследование может быть статически проверено по типам, тогда как делегирование, как правило, невозможно без обобщений (хотя ограниченная версия делегирования может быть статически типобезопасной). [7] ). Делегирование можно назвать «наследованием во время выполнения конкретных объектов».
Вот пример псевдокода на 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()
приведет к b.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)
- Делегирование (программирование)
- Агрегация объектов
- Пересылка (объектно-ориентированное программирование)
Примечания
[ редактировать ]- ^ Бек 1997 использует термины «простое делегирование», когда принимающий объект не имеет доступа к отправляющему объекту, и «самоделегирование», когда принимающий объект имеет доступ к отправляющему объекту; в современном языке это «пересылка» и «делегирование», используемые в этой статье.
Ссылки
[ редактировать ]- ^ Гамма и др. 1995 , «Делегация», стр. 20–21.
- ^ Бек 1997 , «Делегация», стр. 64–69.
- ^ Яблоко (20 августа 2009 г.). «Руководство по основам какао: делегаты и источники данных» . Связь с разработчиками Apple . Проверено 11 сентября 2009 г.
- ^ «Пересекающиеся классы и прототипы». Перспективы системной информатики: 5-я Международная конференция памяти Андрея Ершова, PSI 2003, Академгородок, Новосибирск, Россия, 9-12 июля 2003 г., Переработанные статьи . п. 38 .
- ^ [1] Трюгве Реенскауг , кафедра информатики Университета Осло, «Дело в пользу читаемого кода» (2007).
- ^ Штейн, Линн Андреа. Делегирование — это наследование . OOPSLA '87 Материалы конференции по объектно-ориентированным системам, языкам и приложениям программирования. стр. 138–146. дои : 10.1145/38807.38820 .
- ^ Гюнтер Книзель (19 ноября 1999 г.). «Типобезопасное делегирование для адаптации компонентов времени выполнения» . ЭКООП'99 — Объектно-ориентированное программирование . Конспекты лекций по информатике. Том. 1628. Спрингер. стр. 351–366. CiteSeerX 10.1.1.33.7584 . дои : 10.1007/3-540-48743-3_16 . ISBN 978-3-540-66156-6 . Архивировано из оригинала 4 марта 2015 г. Проверено 4 марта 2015 г.
В этой статье предлагается объектно-ориентированное наследование (также известное как делегирование) в качестве дополнения к композиции объектов, основанной исключительно на пересылке. Он представляет типобезопасную интеграцию делегирования в объектную модель на основе классов и показывает, как она преодолевает проблемы, возникающие при взаимодействии компонентов на основе пересылки, как она поддерживает независимую расширяемость компонентов и непредвиденную динамическую адаптацию компонентов.
{{cite book}}
: CS1 maint: bot: исходный статус URL неизвестен ( ссылка )
- Либерман, Генри (1986). «Использование прототипных объектов для реализации общего поведения в объектно-ориентированных системах» . Материалы конференции «Объектно-ориентированные системы, языки и приложения программирования» . Том. 21. Портленд. стр. 214–223. CiteSeerX 10.1.1.48.69 . дои : 10.1145/960112.28718 .
{{cite book}}
:|journal=
игнорируется ( помощь ) CS1 maint: отсутствует местоположение издателя ( ссылка ) - Линн Андреа Стейн, Генри Либерман, Дэвид Унгар: Общий взгляд на обмен: Орландский договор . В: Вон Ким, Фредерик Х. Лоховский (ред.): Объектно-ориентированные концепции, базы данных и приложения ACM Press, Нью-Йорк, 1989, гл. 3, стр. 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 г. (онлайн в ИТ-университете Копенгагена )
Внешние ссылки
[ редактировать ]- Новый способ реализации Delegate в C++
- Быстрые делегаты в C++
- Проект с открытым исходным кодом PerfectJPattern , обеспечивает многоразовую реализацию делегатов на Java.