Why Matthias Ernst’s “Chaining: A Modest Language Proposal” for Java would be nice to have

OK, shouting at my MP3 player hasn’t been doing me any good; it’s just helping other drivers recognize how passionate I am. ;-> So I’ll try writing about it instead:

After listening to recent Java Posse podcast episodes, I’ve been working my way back to earlier episodes, and I keep tripping over discussions (as in Episide #151) of Matthias Ernst’s “Chaining: A Modest Language Proposal” — which would make the compiler enable a method chaining / “fluid interface” convention on methods returning the void type.

Like the Java Posse members, I’m also somewhat bothered by the idea of reinterpreting void return types, but I think it will be helpful to consider this example of code that would be fixed by his proposal:

Consider these two classes:
public class Base {
  public Base setBaseStuff() { /* ... */ return this; }
}
public class Sub extends Base {
  public Sub setSubStuff() { /* ... */ return this; }
}

This code works:
  new Sub().setSubStuff().setBaseStuff();
This code doesn’t compile:
  new Sub().setBaseStuff().setSubStuff();

The problem is that when you’re using method chaining on classes that extend other classes and which add methods…  You MUST call subclass methods before calling superclass methods.  Otherwise it won’t compile.

With the “Chained Invocations” proposal, if the methods returned void, both method calling orders would compile and work fine.

This happens because the compiler knows more about the type of the callee than the method declaration: When the compiler assumes that void methods return ‘this’, it knows the specific subclass type of ‘this’ — while the method declarations don’t.

In essence…
  new Sub().setBaseStuff().setSubStuff();
becomes
  Sub s = new Sub();
  s.setBaseStuff();
  s.setSubStuff();

This may not seem like much. But what happens when you have a significant number of methods, and possibly several inheritance levels?

Consider these classes:

  public class A {
    public A a1() { /* ... */ return this; }
    public A a2() { /* ... */ return this; }
    public A a3() { /* ... */ return this; }
  }
  public class B extends A {
    public B b1() { /* ... */ return this; }
    public B b2() { /* ... */ return this; }
    public B b3() { /* ... */ return this; }
  }
  public class C extends B {
    public C c1() { /* ... */ return this; }
    public C c2() { /* ... */ return this; }
    public C c3() { /* ... */ return this; }
  }

And this expression:
  new C().c1().c2().c3().b1().b2().b3().a1().a2().a3();

DON’T GET ANY METHOD CALLS OUT OF ORDER!
Like this:
  new C().c1().c2().a2().c3().b1().b2().b3().a1().a3();
OR IT DOESN’T COMPILE!!!

So are we on the same page now, as to why this change might be nice to have?

Advertisements

2 Responses to Why Matthias Ernst’s “Chaining: A Modest Language Proposal” for Java would be nice to have

  1. What you need here is self return types, not method chaining.

    public class Base {
    public This setBaseStuff() { /* … */ return this; }
    }
    public class Sub extends Base {
    public This setSubStuff() { /* … */ return this; }
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: