4

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:

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.

nhoxbypass
  • 149
  • 6

1 Answers1

3

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_(object-oriented_programming)#Language_support_for_delegation

https://en.wikipedia.org/wiki/Delegation_(computing)

https://en.wikipedia.org/wiki/Forwarding_(object-oriented_programming)#Delegation

https://stackoverflow.com/a/37657923/1958683

https://stackoverflow.com/questions/7816011/in-oop-what-is-forwarding-and-how-is-it-different-from-delegation

https://stackoverflow.com/questions/1384426/distinguishing-between-delegation-composition-and-aggregation-java-oo-design

Tugrul ASLAN
  • 181
  • 3
  • The OPs example never refers to `this` one way or another. Leaves me wondering if Java can even truly "forward" – candied_orange Oct 06 '19 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` inherits `a`, there are *two* instances. If you then call a method on `b` (pass a *message* to `b`), if the dispatch mechanism doesn't find a corresponding concrete function on `b`, it automatically resolves it to a concrete function on `a`. The crux of the issue is how the implicit `this` parameter is bound. – Filip Milovanović Oct 06 '19 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 the `a` instance (even though the original call was on `b`), so any mention of `this.whatever` in that function resolves to `a.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ć Oct 06 '19 at 23:42
  • @candied_orange - Delegation involves late binding of `this`, and there, `this` gets bound to the original source, `b`, so `this.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 to `this.someMember` even if `someMember` hasn't been defined anywhere within that scope; then when `this` is bound, it all works out if the bound objects has `someMember`. 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ć Oct 06 '19 at 23:42
  • @FilipMilovanović if this is only about how `this` is bound can't you mess with that using the famous [getThis trick](https://stackoverflow.com/questions/1069528/method-chaining-inheritance-don-t-play-well-together)? – candied_orange Oct 06 '19 at 23:54
  • @candied_orange - You can, but as I understand what all the fuss is about - they (language designers & proponents) are after a universal mechanism for reusable components via delegation of this sort, so it's not enough to rely on different ad hoc tricks, patterns, conventions and such, because different components produced by different people won't work together unless everyone is forced to use the same trick/convention. It's better if it can be made part of the language itself. – Filip Milovanović Oct 07 '19 at 00:02
  • @FilipMilovanović Well heck if you're designing a language you can make it work anyway you want. The OP specifically asked about Java. Makes researching this hard because the examples I'm finding are in JavaScript. – candied_orange Oct 07 '19 at 00:05
  • @candied_orange - Well, that's my point, from what I understand, Java doesn't support delegation, you have to do it manually in some convoluted way - and the OP's example is not it. Also, I just took a closer look at the getThis trick you posted - and that's not it either, because it's just a trick for the return type of the method; `this.name` still refers to the base class member. – Filip Milovanović Oct 07 '19 at 00:11
  • @FilipMilovanović it does? I was sure you got the child's this. Hmm. – candied_orange Oct 07 '19 at 00:26
  • @FilipMilovanović my tests show you get the childs this. The only limitation is that code in the base type doesn't understand what the child's type is so can't refer to new child members. But it can find child values thru base members just fine. To do more than this you'd need a language with duck typing. – candied_orange Oct 08 '19 at 23:46
  • I'm also have the same thought with @FilipMilovanović, they said **"With delegation, the self parameter is bound to the wrapper (this is what we have with the 'this' keyword in Java)"**, but when I test with Java, `this` in wrappee is also point to wrappe not the wrapper. – nhoxbypass Oct 09 '19 at 06:53
  • @nhoxbypass - the Wikipedia article Tugrul ASLAN linked to as the source of the quote doesn't have the part in the parentheses (this is what we have [...] in Java); it's an inline comment that's not marked clearly as such. – Filip Milovanović Oct 10 '19 at 00:45
  • @candied_orange - So, `getThis()` gets the child's this, that's not the issue. But, `this.name` (which appears in the parent's `setName` method) refers to the `name` field declared in the parent. Delegation (according to the definition referenced here, at least) implies that you should be able to declare `name` in the child class - so, yeah, looks like duck typing and late binding of `this` are necessary. Granted, that makes more sense with object-based inheritance; not sure how to feel about it when it comes to class-based languages, though. – Filip Milovanović Oct 10 '19 at 00:47
  • Something just occurred to me: you could simulate it with a virtual/abstract getter (`getName()`), and now that I think about it, that's not too dissimilar from providing the required members in a duck-typed version of the problem - you are implementing the interface (whether implicit or explicit) required by the other component in either case. – Filip Milovanović Oct 10 '19 at 00:56
  • @FilipMilovanović honestly I'm still trying to understand why a receiver acting in its own context can't act on the behalf of the sender. Apparently this is significant to the point that it changes [who pays](https://stackoverflow.com/a/28539643/1493294). I suspect it's actually possible to work around whatever this limitation is so this is really about doing it elegantly. Not sure. Need better examples. – candied_orange Oct 10 '19 at 01:18
  • @FilipMilovanović my tests actually had an abstract `catchPhrase()` that would meow or bark. That I could access even in the base class code using `getThis()`. I still couldn't access `catchMice()` or `catchFrisbie()` because Java won't do duck typing. – candied_orange Oct 10 '19 at 01:32
  • @candied_orange - "why a receiver acting in its own context can't act on the behalf of the sender" - I think "act on behalf" is a peace of jargon leftover from the era of early exploration in OOP, when the ideas were still being developed, and that they used it to specifically denote late-binding of `this` to child/wrapper. I've been going through some of the papers referenced in Wikipedia; it looks like in that early form of object-based inheritance there is no notion of virtual methods, vtables etc., so the ability to override parent/wrappee behavior depended on how `this` was bound. – Filip Milovanović Oct 10 '19 at 20:31
  • @candied_orange - I guess the idea was this. A child instance gets a method call - receives a message, doesn't know what it is, passes it on to parent and there it resolves to a function call (function defined on parent), but the child is passed as the implicit `this` parameter. Then, in that function, whenever you do `this.method(...)` (<=> `child.method(...)`), the whole thing repeats; but if the child understands the message, it's effectively an override. It looks like delegation is an alternative to virtual dispatch. – Filip Milovanović Oct 10 '19 at 20:32
  • @candied_orange - I just did some tests with JavaScript, and I didn't quite realize it until now, delegation in the sense we've been talking about here is pretty much *exactly* how inheritance works in JavaScript; here's a PasteBin of what I've been doing if you want to fiddle with it: https://pastebin.com/tbS5ZiCj – Filip Milovanović Oct 10 '19 at 22:43
  • @FilipMilovanović I'll take a look. I'm starting to wonder how much the advice: "prefer composition over inheritance" might be language dependent. – candied_orange Oct 11 '19 at 20:06