在 OOP 中,什么是转发?它与委托有何不同?
有人可以解释一下转发和委托之间的区别吗?它们看起来很相似,但我一直无法找到转发的良好定义,所以我不确定我是否真的理解。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我们首先定义两个术语:
将消息/任务发送到另一个对象(接收者)的对象
从发送者接收消息/任务的对象
转发和委托之间的区别在于转发
接收者在它自己的上下文中起作用,而在委托
接收者代表发送者行事
。这是这篇博客文章中的一个很好的比喻:
委派和转发非常相似。一个可能有助于区分它们的比喻是,想象一下收到一封电子邮件,要求您向有价值的慈善机构捐款一些钱。
Let's first define two terms:
the object that sends a message/task to another object(the 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 delegationthe 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.
转发有点像“通过包含继承”,或者“以困难的方式实现继承”。
典型的实现继承:
现在,Derived 的实例有一个 baseFn() 方法。这是在不同类之间共享实现的一种方式。
转发看起来像这样:
您也可以通过私有继承来实现它。
委托是转发的一种特殊情况,其中“要转发的对象”是接口本身。
现在,您可以在运行时交换委托的实现,而在转发时则不能(并且您可能不想这样做,这就是您要这样做的原因)。
如果这回答了错误的问题,请在评论中告诉我,我将删除答案。
Forwarding is sort of like "inheritance via containment", or "implementation inheritance the hard way".
Typical implementation inheritance:
Now, an instance of Derived has a baseFn() method. This is a way of sharing implementation between different classes.
Forwarding looks like this:
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.
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.
它们的想法相似,一个对象依赖另一个对象来寻求帮助。鉴于我强烈的 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.