Делегирование (объектно-ориентированное программирование)

редактировать

В объектно-ориентированном программировании, делегирование относится к оценке член (свойство или метод) одного объекта (получателя) в контексте другого исходного объекта (отправителя). Делегирование может быть выполнено явно, путем передачи объекта-отправителя объекту-получателю, что может быть выполнено на любом объектно-ориентированном языке ; или неявно, правилами поиска членов на языке, который требует языковой поддержки для функции. Неявное делегирование является фундаментальным методом повторного использования поведения в программировании на основе прототипов, соответствующем наследованию в программировании на основе классов. Наиболее известными языками, поддерживающими делегирование на уровне языка, являются Self, который включает понятие делегирования через понятие изменяемых родительских слотов, которые используются при поиске метода при самостоятельных вызовах, и JavaScript ; см. Делегирование JavaScript.

Термин делегирование также широко используется для различных других отношений между объектами; подробнее см. делегирование (программирование). Часто путаемые понятия просто используют другой объект, более точно называемый консультацией или агрегированием ; и оценка члена на одном объекте путем оценки соответствующего члена на другом объекте, особенно в контексте принимающего объекта, что более точно называется пересылка (когда объект-оболочка не передает себя в завернутый объект). Шаблон делегирования - это шаблон проектирования программного обеспечения для реализации делегирования, хотя этот термин также используется в широком смысле для консультации или пересылки.

Содержание
  • 1 Обзор
  • 2 Поддержка языков для делегирования
    • 2.1 Двойное наследование
    • 2.2 Связанные области
  • 3 См. Также
  • 4 Примечания
  • 5 Ссылки
  • 6 Внешние ссылки
Обзор

Это ощущение делегирования как функции языка программирования, использующей правила поиска методов для так называемой диспетчеризации, было определено Либерманом в его статье 1986 года «Использование прототипических объектов для Реализация общего поведения в объектно-ориентированных системах ».

Делегирование зависит от динамической привязки, так как требует, чтобы вызов данного метода мог вызывать различные сегменты кода во время выполнения. Он используется в macOS (и в его предшественнице NeXTStep ) как средство настройки поведения компонентов программы. Он позволяет реализовать такие реализации, как использование одного класса, предоставляемого ОС, для управления окнами, поскольку класс принимает делегат, зависящий от программы, и может при необходимости переопределять поведение по умолчанию. Например, когда пользователь щелкает поле закрытия, диспетчер окон отправляет делегату вызов windowShouldClose:, и делегат может отложить закрытие окна, если есть несохраненные данные, представленные содержимым окна.

Делегирование можно охарактеризовать (и отличить от пересылки ) как позднюю привязку self:

... сообщения, отправленные на self(или эта) переменная в родительском объекте "вернется" к объекту, который изначально получил сообщение.

То есть selfв определении метода в принимающем объекте не статически привязан к этот объект во время определения (например, во время компиляции или когда функция прикреплена к объекту), но, скорее, во время оценки он привязан к исходному объекту.

Утверждалось, что в некоторых случаях делегирование может быть предпочтительнее наследования, чтобы сделать программный код более читаемым и понятным. Несмотря на то, что явное делегирование довольно широко распространено, относительно немногие основные языки программирования реализуют делегирование в качестве модели, альтернативной наследованию. Точная связь между делегированием и наследованием сложна; некоторые авторы считают их эквивалентными, или одно - частным случаем другого.

Языковая поддержка делегирования

В языках, которые поддерживают делегирование через правила поиска методов, диспетчеризация методов определяется так, как это определено для виртуальных методов в наследовании: при поиске метода всегда выбирается наиболее конкретный метод. Следовательно, именно исходный объект-получатель является началом поиска метода, даже если он передал управление какому-то другому объекту (через ссылку делегирования, а не ссылку на объект).

Преимущество делегирования в том, что оно может происходить во время выполнения и затрагивать только подмножество сущностей определенного типа и даже может быть удалено во время выполнения. Наследование, напротив, обычно нацелено на тип, а не на экземпляры, и ограничивается временем компиляции. С другой стороны, наследование может быть статически проверено типом, в то время как делегирование обычно не может быть без дженериков (хотя ограниченная версия делегирования может быть статически типизированной). Делегирование можно назвать «наследованием во время выполнения для определенных объектов».

Вот пример псевдокода на C# /Java подобном языке:

class A {void foo () {// "this" также известен под именами «текущий», «я» и «я» на других языках this.bar (); } void bar () {print ("a.bar"); }}; class B {частный делегат A a; // делегирование ссылки public B (A a) {this.a = a; } void foo () {a.foo (); // вызываем foo () в экземпляре a} void bar () {print ("b.bar"); }}; a = новый A (); b = новый B (a); // устанавливаем делегирование между двумя объектами

Вызов 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"); }}; класс B расширяет A {public B () {} void foo () {super.foo (); // вызов функции foo () суперкласса (A)} void bar () {print ("B.bar"); }}; b = новый B ();

Вызов b.foo ()приведет к B.bar . В этом случае thisоднозначно: существует единственный объект, b, а this.bar ()преобразуется в метод подкласса.

Языки программирования в целом не поддерживают эту необычную форму делегирования как концепцию языка, но есть несколько исключений.

Двойное наследование

Если язык поддерживает и делегирование, и наследование, можно выполнить двойное наследование, используя оба механизма одновременно, как в

класс C расширяет A {делегирование ссылки D d; }

Это требует дополнительных правил для поиска методов, поскольку теперь потенциально есть два метода, которые можно обозначить как наиболее специфичные (из-за двух путей поиска).

Связанные области

Делегирование можно описать как низкоуровневый механизм для совместного использования кода и данных между объектами. Таким образом, он закладывает основу для других языковых конструкций. Примечательно, что языки ролевого программирования использовали делегирование, но особенно старые фактически использовали агрегацию, утверждая, что используют делегирование. Это не следует рассматривать как обман, это просто множественное определение того, что означает делегирование (как описано выше).

Совсем недавно была проделана работа по распределению делегирования, например, клиенты поисковой системы (поиск дешевых гостиничных номеров) могут использовать общую сущность, используя делегирование, чтобы делиться лучшими результатами и общей функциональностью многократного использования.

Делегирование также было предложено для разрешения рекомендаций в аспектно-ориентированном программировании Эрнстом и Лоренцем в 2003 году.

См. Также

Отличительные особенности:

Примечания
Ссылки
Внешние ссылки
Последняя правка сделана 2021-05-17 12:03:35
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте