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

发布于 2024-12-10 19:27:22 字数 66 浏览 0 评论 0原文

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

Would someone please explain the difference between forwarding and delegation? They seem similar, but I haven't been able to find a good definition of forwarding, so I'm not sure I really understand.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

帅气称霸 2024-12-17 19:27:22

我们首先定义两个术语:

  • 发送者将消息/任务发送到另一个对象(接收者)的对象
  • 接收者从发送者接收消息/任务的对象

转发委托之间的区别在于转发接收者在它自己的上下文中起作用,而在委托 接收者代表发送者行事

这是这篇博客文章中的一个很好的比喻:

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

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

Let's first define two terms:

  • sender : the object that sends a message/task to another object(the receiver)
  • receiver: the object that receives a message/task from the sender

The difference between forwarding and delegation is that in forwarding the receiver acts in its own context whereas in delegation the receiver acts on the behalf of the sender.

Here is a great metaphor from this blog post:

Delegation and forwarding are both very similar. One metaphor that might help distinguish them is to think of receiving an email asking you to donate some money to a worthy charity.

  • If you forward the email to a friend, and the friend donates money, the friend is donating their own money and getting their own tax receipt.
  • If you delegate responding to your accountant, the accountant donates your money to the charity and you receive the tax receipt.
三月梨花 2024-12-17 19:27:22

转发有点像“通过包含继承”,或者“以困难的方式实现继承”。

典型的实现继承:

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.
};

现在,您可以在运行时交换委托的实现,而在转发时则不能(并且您可能不想这样做,这就是您要这样做的原因)。

如果这回答了错误的问题,请在评论中告诉我,我将删除答案。

Forwarding is sort of like "inheritance via containment", or "implementation inheritance the hard way".

Typical implementation inheritance:

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

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

Now, an instance of Derived has a baseFn() method. This is a way of sharing implementation between different classes.

Forwarding looks like this:

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

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

You could have also implemented that with private inheritance.

Delegation is a special case of forwarding, where at the "thing to forward" to is an interface itself.

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.
};

Now, you can swap out the implementation of delegate at runtime, whereas in forwarding you cannot (and you may not want to, which is why you would do it).

If that answers the wrong question, let me know in a comment and I'll remove the answer.

晨曦÷微暖 2024-12-17 19:27:22

它们的想法相似,一个对象依赖另一个对象来寻求帮助。鉴于我强烈的 Objective-C 偏见,我对这两个想法的看法如下:

委托:需要做出决定,但我不想做出。我会让我的代表来处理这件事。

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

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

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

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

They're similar ideas in that one object relies on another for help. Here's how I think of the two ideas given my strong Objective-C bias:

delegation: A decision needs to be made, but I don't want to make it. I'll let my delegate handle that.

In Cocoa, for example, NSTableView uses a delegate to customize the behavior of the table. Delegation provides a way to customize one object by letting another object, the delegate, provide the customization. Continuing with the example, a table view's delegate implements an NSTableViewDelegate interface that the table uses to talk to its delegate.

forwarding: Someone just sent me a message that I don't understand, but I know of another object that might implement it. I'll pass the invocation of that message on to that object.

In Cocoa, again, any class can implement the -forwardInvocation: method. If a message is sent to an object that doesn't implement it, that object's -forwardInvocation: method is called, and the object can decide to pass the invocation on to another object. That object could be its delegate, or it could be some system-wide error handler, or whatever. NSProxy uses this to appear to implement all methods -- it just passes the invocation on to its master object.

Note that with forwarding, there's not a defined delegate interface; the message is just passed on to another object. Another place you see what I'd call forwarding is when one object contains another object that it uses to implement some interface. Any messages to that interface are just forwarded to the contained object, which does all the work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文