<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div>We may need something like this for Valhalla, when we will revisit how to constraint the type arguments of universal generics.<br></div><div><br data-mce-bogus="1"></div><div>The kind of constraints you describe on type parameters already exist in C# or TypeScript and was more recently introduced in Go, and there is the type class of Haskell too.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>regards,<br data-mce-bogus="1"></div><div>RĂ©mi<br data-mce-bogus="1"></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Red IO" <redio.development@gmail.com><br><b>To: </b>"amber-dev" <amber-dev@openjdk.org><br><b>Sent: </b>Wednesday, January 25, 2023 8:03:14 AM<br><b>Subject: </b>Constructor Interfaces<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="auto"><div dir="auto">Summary</div><div dir="auto">-------</div><div dir="auto"><br></div><div dir="auto">Enable a parameterized class to constrain the parameterized type to be constructible with a given list of parameters.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">Motivation</div><div dir="auto">----------</div><div dir="auto"><br></div><div dir="auto">It is possible since JDK 8 to get a constructor (method) reference of an object. This allowed for the creation of an unknown class with a known constructor reference. But currently the only way to obtain such reference is at call site like this:</div><div dir="auto"><span style="white-space:pre"> </span></div><div dir="auto"><span style="white-space:pre"> </span>Box<String> stringBox = new Box<>(String::new);</div><div dir="auto"><br></div><div dir="auto">It is inconvenient for the user to supply the the reference themselves and can confuse them as the type of the parameter is something like Supplier<String> which doesn't require the pased reference to be a constructor. </div><div dir="auto">It also clutters api's like "toArray" which requires an IntFunction to be type safe. </div><div dir="auto"><br></div><div dir="auto">Description</div><div dir="auto">-----------</div><div dir="auto"><br></div><div dir="auto">ConstructorInterface</div><div dir="auto">A ConstructorInterface is a special kind of interface similar to a FunctionalInterface. It also has similar constraints. It only allows abstract constructors and no other abstract methods. It can declare multiple constructors though. The definition of such interface would look similar to this:</div><div dir="auto"><br></div><div dir="auto"><span style="white-space:pre"> </span>@ConstructorInterface //optional validation like FunctionalInterfaces</div><div dir="auto"><span style="white-space:pre"> </span>public interface DefaultConstructible {</div><div dir="auto"><span style="white-space:pre"> </span>new();</div><div dir="auto"><span style="white-space:pre"> </span>new(char[] chars);</div><div dir="auto"><span style="white-space:pre"> </span>}</div><div dir="auto"><br></div><div dir="auto">A parameterized type could declare this interface as a type bound for its parameter and therefore enabling it to be constructed safely. Like this:</div><div dir="auto"><span style="white-space:pre"> </span>public class Box<E extends DefaultConstructible> {</div><div dir="auto"><span style="white-space:pre"> </span>public Box() {</div><div dir="auto"><span style="white-space:pre"> </span>E newElement = new E();</div><div dir="auto"><span style="white-space:pre"> </span>}</div><div dir="auto"><span style="white-space:pre"> </span>}</div><div dir="auto">The containing type is not forced to implement the ContructorInterface explicitly. It is implicitly implemented if the required constructor(s) is(are) present.</div><div dir="auto"><span style="white-space:pre"> </span>public static void main(String[] args) {</div><div dir="auto"><span style="white-space:pre"> </span>Box<String> stringBox = new Box<>(); //compiles because String has the required constructors.</div><div dir="auto"><span style="white-space:pre"> </span>Box<java.sql.Date> dateBox new Box<>(); error: java.sql.Data does not satisfy the type bound DefaultConstructible</div><div dir="auto"><span style="white-space:pre"> </span>}</div><div dir="auto">The interface might not be implemented by any class, since it doesn't follow the inheritance rule that extending classes of those who implement it also implement it. This requirement comes from the fact that extending classes do not necessarily need to have the same constructor signature and therefore don't qualify the requirements for the interface. Another option would be that extending classes of classes that implement a constructor interface explicitly are also required to supply the necessary constructors.</div><div dir="auto"><br></div><div dir="auto">class Foo implements DefaultConstructable {</div><div dir="auto"><span style="white-space:pre"> </span>//both required by the interface </div><div dir="auto"><span style="white-space:pre"> </span>public Foo() {} </div><div dir="auto"><span style="white-space:pre"> </span>public Foo(char[] chars) {} </div><div dir="auto">} </div><div dir="auto"><br></div><div dir="auto">class Bar extends Foo {</div><div dir="auto"><span style="white-space:pre"> </span>//the requirement for the required constructors is passed down. </div><div dir="auto"><span style="white-space:pre"> </span>public Bar() {} </div><div dir="auto"><span style="white-space:pre"> </span>public Bar(char[] chars) {} </div><div dir="auto">} </div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">public static <T extends Foo> T createT() {</div><div dir="auto"><span style="white-space:pre"> </span>return new T();</div><div dir="auto">} </div><div dir="auto"><br></div><div dir="auto">public <T extends Foo> T wrapper() {</div><div dir="auto"><span style="white-space:pre"> </span>return createT();</div><div dir="auto">} </div><div dir="auto">This would technically work but would require a lot of static analysis to find the real type of T to call its constructor. </div><div dir="auto">Restricting the use of "new T()" to type parameters that specify a constructor interface directly and only allow those to be resolved with a concrete type rather than another type parameter. </div><div dir="auto"><br></div><div dir="auto">Alternatives</div><div dir="auto">------------</div><div dir="auto">An alternative would be to introduce new syntax to restrict the ability of certain constructors on a parameter type. Like c# does (but only for the default constructor) :</div><div dir="auto">public static T foo<T>() where T: new() {</div><div dir="auto"><span style="white-space:pre"> </span>return new T();</div><div dir="auto">} </div><div dir="auto">In java:</div><div dir="auto">public static <T extends new()> T foo() {</div><div dir="auto"><span style="white-space:pre"> </span>return new T();</div><div dir="auto">} </div><div dir="auto">The downside of this approach is obviously the introduction of new syntax rather than reusing the interface/inheritance syntax. </div><div dir="auto"><br></div><div dir="auto">Another alternative to this approach could be to implement static abstract methods. This would allow an interface to mandate a static Factory Method. The downside of this approach is that it requires the parameter class to actually implement the interface and the concept of type erasure would need to be addressed for static abstract methods to work. In contrast the ConstructorInterface enables every class that matches its contract to pass the type bound.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">Risks and Assumptions</div><div dir="auto">---------------------</div><div dir="auto"><br></div><div dir="auto">As mentioned before the restriction the interface is giving on a type bound is different to normal interfaces, it restricts by its containing abstract constructors not by the type itself. It also makes use of the new operator on type variables. </div><div dir="auto"></div></div><br></blockquote></div></div></body></html>