В ООП, что такое пересылка и чем она отличается от делегирования?

Кто-нибудь, пожалуйста, объяснит разницу между пересылкой и делегированием? Они кажутся похожими, но я не смог найти хорошее определение пересылки, поэтому я не уверен, что действительно понимаю.

Ответы

Ответ 1

Переадресация похожа на "наследование через сдерживание", или "наследование реализации - трудный путь".

Типичное наследование реализации:

class Base
{
 public:
    void baseFn() { }
};

class Derived : public Base
{
 public:
    void derivedFn() { }
};

Теперь экземпляр Derived имеет метод baseFn(). Это способ совместного использования между различными классами.

Пересылка выглядит следующим образом:

class Contained
{
 public:
    void containedFn() { }
};

class Thing
{
 public:
    void thingFn() { }
    void containedFn() { mContained.containedFn(); }
 private:
    Contained mContained;
};

Вы могли бы также реализовать это с частным наследованием.

Делегирование - это особый случай переадресации, где в "вещи переслать" это сам интерфейс.

class Delegate
{
 public:
    virtual void doDelegateAction() = 0;
};

class DelegateA : public Delegate
{
    virtual void doDelegateAction() { }
};

class DelegateB : public Delegate
{
    virtual void doDelegateAction() { }
};

class Thing
{
 public:
    void Thing (Delegate * delegate) { mDelegate = delegate; }
    void thingFn() { }
    void containedFn() { if (mDelegate) mDelegate->doDelegateAction(); }
 private:
    Delegate * mDelegate; // Note, we don't own this memory, buyer beware.
};

Теперь вы можете поменять реализацию делегата во время выполнения, тогда как при пересылке вы не можете (и вы не можете этого захотеть, поэтому вы это сделаете).

Если это ответит на неправильный вопрос, дайте мне знать в комментарии, и я удалю ответ.

Ответ 2

Сначала определим два члена:

  • отправитель: the object that sends a message/task to another object(the receiver)
  • : the object that receives a message/task from the sender

Разница между пересылкой и делегированием заключается в том, что при переадресации the receiver acts in its own context тогда как в делеции the receiver acts on the behalf of the sender.

Вот отличная метафора из этого сообщения в блоге:

Делегирование и пересылка очень похожи. Одна метафора, которая может помочь их отличить, состоит в том, чтобы подумать о получении электронного письма с просьбой пожертвовать деньги достойной благотворительности.

  • Если вы перешлите письмо другу, а друг пожертвует деньги, друг пожертвует свои собственные деньги и получит свою собственную налоговую квитанцию.
  • Если вы делегируете ответите на своего бухгалтера, бухгалтера жертвует ваши деньги на благотворительность, и вы получаете налоговую квитанцию.

Ответ 3

Они похожи на идеи в том, что один объект полагается на другой для помощи. Здесь, как я думаю о двух идеях, учитывая мой сильный Objective-C смещение:

делегирование: Необходимо принять решение, но я не хочу этого делать. Я позволю своему делегату справиться с этим.

В Cocoa, например, NSTableView использует делегат для настройки поведения таблицы. Делегирование предоставляет способ настройки одного объекта, позволяя другому объекту, делегату, обеспечить настройку. Продолжая этот пример, делегат представления таблиц реализует NSTableViewDelegate интерфейс, который использует таблица, чтобы поговорить с его делегатом.

пересылка: Кто-то просто отправил мне сообщение, которое я не понимаю, но я знаю другого объекта, который мог бы его реализовать. Я передам вызов этого сообщения этому объекту.

В Cocoa, опять же, любой класс может реализовать метод - forwardInvocation:. Если сообщение отправляется объекту, который его не реализует, этот метод -forwardInvocation: вызывается, и объект может решить передать вызов другому объекту. Этот объект может быть его делегатом, или это может быть какой-то системный обработчик ошибок или что-то еще. NSProxy использует это для реализации всех методов - он просто передает вызов на свой главный объект.

Обратите внимание, что при пересылке нет определенного интерфейса делегата; сообщение просто передается другому объекту. Другое место, которое вы видите, то, что я вызываю переадресацией, - это когда один объект содержит другой объект, который он использует для реализации некоторого интерфейса. Любые сообщения для этого интерфейса просто перенаправляются на содержащийся объект, который выполняет всю работу.