I'm reading some article about "prefer composition over inheritance", and heard about Forwarding and Delegation. After search for the different I found some source:
- https://en.wikipedia.org/wiki/Forwarding_(object-oriented_programming)
- https://en.wikipedia.org/wiki/Delegation_(object-oriented_programming)
- https://www.geeksforgeeks.org/delegation-vs-inheritance-java/
But these example is make me more confused. For example, with this snippet of code:
class RealPrinter { // the "receiver"
void print() {
System.out.println("Hello world!");
}
}
class Printer { // the "sender"
RealPrinter p = new RealPrinter(); // create the receiver
void print() {
p.print(); // calls the receiver
}
}
public class Main {
public static void main(String[] arguments) { // to the outside world it looks like Printer actually prints.
Printer printer = new Printer();
printer.print();
}
}
Wikipedia said it's Forwarding, but GeeksForGeeks said it's Delegation. So which is right?
Another thing is in Wikipedia's example they declare the delegation using private delegate A a;
, which is delegate
keyword?
And what is "real life" example of Forwarding vs Delegation, with example code in Java.
1 Answer 1
I have known about the Delegation normally as you have demonstrated in your answer, but not the Forwarding.
Short answer: what you provided with the Printer code snippet is Delegation. On top of that, the given Wikipedia example 1 is yet another acceptable answer as well.
Long Answer:
I'll break the descriptions down which makes it easier to apprehend the terms and the concepts.
A simple visual to better explain the given terms :
=========================
| WRAPPER(Sending) |
| +---------------+ |
| + WRAPPEE + |
| + (Receiving) + |
| +---------------+ |
| |
=========================
The Delegation
evaluating a member of one object (the receiver) in the context of another, original object (the sender). 2
This indicates to what we know from printer example. The Wrapper
The Forwarding
An often-confused technique where a sending object uses the corresponding member of another object, without the receiving object having any knowledge of the original, sending object.2
In addition, the slight difference between Delegation and Forwarding is that how the "self" keyword is bounded, according to Wikipedia;
They differ in what self refers to on the receiving object (formally, in the evaluation environment of the method on the receiving object): in delegation it refers to the sending object, while in forwarding it refers to the receiving object.3
Furthermore, the definition goes on as;
The difference between forwarding and delegation is the binding of the self parameter in the wrappee when called through the wrapper. With delegation, the self parameter is bound to the wrapper(this is what we have with the 'this' keyword in Java), with forwarding it is bound to the wrappee.3
In essence, for the sake of the Forwarding, the Receiving object should not know the details of the Sending object. This stackoverflow answer 4 explains in details the "this" and the "self" keywords in Java and Python that will give you some understanding of the Forwarding breakdown.
However, I have found out also different answers in the context of Delegation and Forwarding. I sense that there can be mixed opinions 5, 6
https://en.wikipedia.org/wiki/Delegation_(computing)
https://en.wikipedia.org/wiki/Forwarding_(object-oriented_programming)#Delegation
-
The OPs example never refers to
this
one way or another. Leaves me wondering if Java can even truly "forward"candied_orange– candied_orange2019年10月06日 17:34:14 +00:00Commented Oct 6, 2019 at 17:34 -
1@candied_orange - Actually, i think it can, but it can't delegate. This whole thing is confusing when thinking in modern terms; I think it originated in the context of classless, prototype-based inheritance (an instance has a parent instance); so the thinking is, if an object
b
inheritsa
, there are two instances. If you then call a method onb
(pass a message tob
), if the dispatch mechanism doesn't find a corresponding concrete function onb
, it automatically resolves it to a concrete function ona
. The crux of the issue is how the implicitthis
parameter is bound.Filip Milovanović– Filip Milovanović2019年10月06日 23:41:37 +00:00Commented Oct 6, 2019 at 23:41 -
1@candied_orange - If you think about class-based languages in this way, the standard behavior that we are all used to is that in the function that finally gets called,
this
gets bound to thea
instance (even though the original call was onb
), so any mention ofthis.whatever
in that function resolves toa.whatever
(base class can't explicitly refer to any derived member). If I'm not mistaken, that's forwarding according to this definition.Filip Milovanović– Filip Milovanović2019年10月06日 23:42:34 +00:00Commented Oct 6, 2019 at 23:42 -
@candied_orange - Delegation involves late binding of
this
, and there,this
gets bound to the original source,b
, sothis.whatever
sends the message back to the original object. To do this, the language has to provide the ability to write code where you can refer tothis.someMember
even ifsomeMember
hasn't been defined anywhere within that scope; then whenthis
is bound, it all works out if the bound objects hassomeMember
. You can do this in JavaScript using call; e.g.let f = function () { console.log(this.x); }; let o = { x: 42 }; f.call(o)
(doesn't work with lambdas).Filip Milovanović– Filip Milovanović2019年10月06日 23:42:54 +00:00Commented Oct 6, 2019 at 23:42 -
@FilipMilovanović if this is only about how
this
is bound can't you mess with that using the famous getThis trick?candied_orange– candied_orange2019年10月06日 23:54:17 +00:00Commented Oct 6, 2019 at 23:54
Explore related questions
See similar questions with these tags.