在OOP中,什么是转发,它与委托有什么不同?

时间:2011-10-19 02:45:44

标签: c++ oop class delegation forwarding

有人请解释转发和委派之间的区别吗?它们看起来很相似,但我找不到转发的好定义,所以我不确定我是否真的理解。

3 个答案:

答案 0 :(得分:11)

让我们先定义两个术语:

  • 发件人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,而在委托 { {1}}。

以下是blog post的一个很好的比喻:

委派和转发都非常相似。一个可能有助于区分它们的比喻是想到收到一封电子邮件,要求你向一个有价值的慈善机构捐款。

  • 如果您转发该电子邮件给朋友,并且该朋友捐款,该朋友捐出自己的钱并获得自己的税收收据。
  • 如果您委托回复您的会计师,会计会将您的钱捐赠给慈善机构,并且您会收到税务收据。

答案 1 :(得分:10)

转发有点像“通过遏制继承”,或“艰难实施继承”。

典型的实现继承:

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 :(得分:2)

他们是类似的想法,因为一个对象依赖另一个对象寻求帮助。考虑到我强烈的Objective-C偏见,这就是我对这两个想法的看法:

授权:需要做出决定,但我不想做出决定。我会让我的代表处理。

例如,在Cocoa中,NSTableView使用委托来自定义表的行为。委派提供了一种通过让另一个对象(委托)提供自定义来自定义一个对象的方法。继续该示例,表视图的委托实现了一个NSTableViewDelegate接口,该表用于与其委托进行通信。

转发:有人刚给我发了一条我不理解的消息,但我知道另一个可能实现它的对象。我将把该消息的调用传递给该对象。

在Cocoa中,任何类都可以实现-forwardInvocation:方法。如果将消息发送到未实现它的对象,则调用该对象的-forwardInvocation:方法,并且该对象可以决定将调用传递给另一个对象。该对象可以是它的委托,也可以是一些系统范围的错误处理程序,或者其他什么。 NSProxy使用它来实现所有方法 - 它只是将调用传递给它的主对象。

请注意,转发时,没有已定义的委托接口;消息只是传递给另一个对象。另一个你看到我称之为转发的地方是当一个对象包含另一个用于实现某个接口的对象时。任何发送到该接口的消息都只会转发到包含的对象,该对象可以完成所有工作。