<div dir="ltr"><div>You can solve this problem by generifying the <span style="font-family:monospace">Shape</span> class.</div><div><br></div><div><span style="font-family:monospace">public class Shape<T extends Shape<?>> {<br>    public T scale(double ratio) {<br>        return (T) this;<br>    }<br>}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">public class Rectangle extends Shape<Rectangle> {<br>    public Rectangle roundCorners(double pixels) {<br>        return this;<br>    }<br>}</span></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jun 8, 2023 at 6:12 AM <<a href="mailto:blesa@anneca.cz">blesa@anneca.cz</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;"><div>Hi all,</div><div><br></div>this is a request for feedback on a topic that has been on my mind for a few weeks. I have written a short document in JEP format and would like to ask you to comment if you find the described proposal useful.<div><br></div><div>Thanks,</div><div>Tomas Blesa</div><div><br></div><div>===========================</div><div><br></div><div><div><font style="font-size:14px" face="Menlo">Summary</font></div><div><font style="font-size:14px" face="Menlo">-------</font></div><div><font style="font-size:14px" face="Menlo">Enhance the Java language syntax to better support the method chaining (named parameter idiom) programming pattern.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Goals</font></div><div><font style="font-size:14px" face="Menlo">-----</font></div><div><font style="font-size:14px" face="Menlo">The primary goal is to remove unnecessary boilerplate code in class methods designed for type-safe chained calls, especially when combined with inheritance.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Motivation</font></div><div><font style="font-size:14px" face="Menlo">----------</font></div><div><font style="font-size:14px" face="Menlo">[Method chaining](<a href="https://en.wikipedia.org/wiki/Method_chaining" target="_blank">https://en.wikipedia.org/wiki/Method_chaining</a>) is a widely used and popular programming pattern, particularly in creating libraries (APIs) or configuration objects. Programmers can easily create a method that returns `this` with a method signature that specifies the returning type of the containing class.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class Shape {</font></div><div><font style="font-size:14px" face="Menlo">    public Shape scale(double ratio) {</font></div><div><font style="font-size:14px" face="Menlo">        // recalculate all points</font></div><div><font style="font-size:14px" face="Menlo">        return this;</font></div><div><font style="font-size:14px" face="Menlo">    }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">The problem arises when we combine this pattern with inheritance. We can lose type information when calling the method on a subclass. For example, let's create two subclasses of the `Shape` superclass:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class Rectangle extends Shape {</font></div><div><font style="font-size:14px" face="Menlo">    public Rectangle roundCorners(double pixels) {</font></div><div><font style="font-size:14px" face="Menlo">        // ...</font></div><div><font style="font-size:14px" face="Menlo">        return this;</font></div><div><font style="font-size:14px" face="Menlo">    }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">class Circle extends Shape {</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Now, imagine the following piece of code using the mini-library above:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">var myRect = new Rectangle().scale(1.2).roundCorners(10);</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">The code won't compile because `scale()` returns the type `Shape`, which doesn't have the `roundCorners` method. There is also a problem even without the final `roundCorners()` call:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">var myRect = new Rectangle().scale(1.2);</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">The inferred type of `myRect` is `Shape` and not `Rectangle`, so the following line will also be invalid:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">myRect.roundCorners(10);</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Straightforward solutions to the problem could be:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">1) Override the `scale()` method in all subclasses and change the return type:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class Rectangle extends Shape {</font></div><div><font style="font-size:14px" face="Menlo">    // ...</font></div><div><font style="font-size:14px" face="Menlo">    @Override</font></div><div><font style="font-size:14px" face="Menlo">    public Rectangle scale(double ratio) {</font></div><div><font style="font-size:14px" face="Menlo">        super.scale(ratio);</font></div><div><font style="font-size:14px" face="Menlo">        return this;</font></div><div><font style="font-size:14px" face="Menlo">    }       </font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">2) Split object construction and method calls:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">var myRect = new Rectangle();</font></div><div><font style="font-size:14px" face="Menlo">myRect.scale(1.2);</font></div><div><font style="font-size:14px" face="Menlo">myRect.roundCorners(10);</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">3) Partial solution - reorder chained calls (if possible):</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">var myRect = new Rectangle();</font></div><div><font style="font-size:14px" face="Menlo">myRect.roundCorners(10).scale(1.2); // roundCorners called first</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">All of these solutions add unnecessary lines of code, and as the library of shapes grows, keeping the desired return type will introduce more and more boilerplate code.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Description</font></div><div><font style="font-size:14px" face="Menlo">-----------</font></div><div><font style="font-size:14px" face="Menlo">The proposed solution to the problem described in the previous section is to extend the Java syntax for the returned type in method signatures:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class Shape {</font></div><div><font style="font-size:14px" face="Menlo">    public this scale(double ratio) { // <=== returned this</font></div><div><font style="font-size:14px" face="Menlo">        // recalculate all points</font></div><div><font style="font-size:14px" face="Menlo">        return this;</font></div><div><font style="font-size:14px" face="Menlo">    }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Methods declared or defined as returning `this` can only return the instance on which they are called. The following code will be type-safe and perfectly valid:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">var myRect =                     // inferred Rectangle type</font></div><div><font style="font-size:14px" face="Menlo">    new Rectangle()              // returns Rectangle instance</font></div><div><font style="font-size:14px" face="Menlo">    .scale(1.2)                  // returns Rectangle instance</font></div><div><font style="font-size:14px" face="Menlo">    .roundCorners(10);           // returns Rectangle instance</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">The constructed type `Rectangle` is preserved throughout the entire call chain.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">It will be possible to override methods returning `this`, but the subclass' implementation must also be declared with the `this` keyword instead of a concrete returning type.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">It is even possible to remove the explicit return statement altogether:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class Shape {</font></div><div><font style="font-size:14px" face="Menlo">    public this scale(double ratio) {</font></div><div><font style="font-size:14px" face="Menlo">        // recalculate all points</font></div><div><font style="font-size:14px" face="Menlo">    }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Or simply remove the value `this` from the return statement:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class Shape {</font></div><div><font style="font-size:14px" face="Menlo">    public this scale(double ratio) {</font></div><div><font style="font-size:14px" face="Menlo">        // recalculate all points</font></div><div><font style="font-size:14px" face="Menlo">        if (condition) return;         // <== automatically returns this</font></div><div><font style="font-size:14px" face="Menlo">        // do something else</font></div><div><font style="font-size:14px" face="Menlo">    }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">In the Java world, it is common to create getters and setters according to the Java Beans specification in the form of `getProperty`/`setProperty` pairs or `isProperty`/`setProperty`. Setters are defined as returning `void`. These setters can be more useful if defined as returning `this`:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class Customer {</font></div><div><font style="font-size:14px" face="Menlo">    public this setFirstname() { ... }</font></div><div><font style="font-size:14px" face="Menlo">    public this setSurname() { ... }</font></div><div><font style="font-size:14px" face="Menlo">    public this setEmail() { ... }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">This allows for more concise usage when constructing and configuring an instance without adding more code:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">customers.add(</font></div><div><font style="font-size:14px" face="Menlo">    new Customer()</font></div><div><font style="font-size:14px" face="Menlo">        .setFirstname(resultSet.getString(1))</font></div><div><font style="font-size:14px" face="Menlo">        .setSurname(resultSet.getString(2))</font></div><div><font style="font-size:14px" face="Menlo">        .setEmail(resultSet.getString(3))</font></div><div><font style="font-size:14px" face="Menlo">);</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">It is also possible to declare an interface with methods returning `this`:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">interface Shape {</font></div><div><font style="font-size:14px" face="Menlo">    this scale(double ratio);</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">In this case, all implementing classes must define the method as returning `this`.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">The proposed syntax is a bit less useful for enums or records, as neither of them allows for inheritance. But enums and records can also implement interfaces and for this reason and for overall consistency, "return this" syntax should be allowed for enums and records.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">To accommodate the syntax with the Java Reflection API, it will probably be required to create a special final placeholder class `This` (with an uppercase "T"), similar to `java.lang.Void`.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Alternatives</font></div><div><font style="font-size:14px" face="Menlo">------------</font></div><div><font style="font-size:14px" face="Menlo">It is probably possible to help auto-generate overriding methods in subclasses using annotation processing, but this option wasn't fully explored. However, such an approach would add extra unnecessary code to compiled subclasses and go against the primary goal of reducing boilerplate.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Risks and Assumptions</font></div><div><font style="font-size:14px" face="Menlo">---------------------</font></div><div><font style="font-size:14px" face="Menlo">The proposed syntax is likely to break the compatibility of library-dependent code whose author decides to switch to the "return this" syntax between versions.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Older code that looks like this:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class MyUglyShape extends Shape {</font></div><div><font style="font-size:14px" face="Menlo">    @Override</font></div><div><font style="font-size:14px" face="Menlo">    public MyUglyShape scale(double ratio) {</font></div><div><font style="font-size:14px" face="Menlo">        return this;</font></div><div><font style="font-size:14px" face="Menlo">    }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">will have to be rewritten as:</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class MyUglyShape extends Shape {</font></div><div><font style="font-size:14px" face="Menlo">    @Override</font></div><div><font style="font-size:14px" face="Menlo">    public this scale(double ratio) {    // signature change</font></div><div><font style="font-size:14px" face="Menlo">        // optional removal of the return this statement</font></div><div><font style="font-size:14px" face="Menlo">    }</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">or </font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">```java</font></div><div><font style="font-size:14px" face="Menlo">class MyUglyShape extends Shape {</font></div><div><font style="font-size:14px" face="Menlo"><span style="white-space:pre-wrap">     </span>// override removed</font></div><div><font style="font-size:14px" face="Menlo">}</font></div><div><font style="font-size:14px" face="Menlo">```</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">This problem can be mitigated with the help of smart IDEs automatically suggesting such refactoring.</font></div><div><font style="font-size:14px" face="Menlo"><br></font></div><div><font style="font-size:14px" face="Menlo">Another possible risk is breaking old code that relies on the Reflection API for scanning the returning types of methods.</font></div></div></div></blockquote></div>