Constructor Interfaces
Red IO
redio.development at gmail.com
Wed Jan 25 14:17:34 UTC 2023
I proposed an idea (to Valhalla) to overcome type erasure that used the
same idea of desugering and a hidden argument that carries the erased types
class variable inside the generic context, but it was rejected as a to
naive approach or something and they where "already working on different
solutions for some time".
Great regards RedIODev
On Wed, Jan 25, 2023, 14:51 Remi Forax <forax at univ-mlv.fr> wrote:
> We may need something like this for Valhalla, when we will revisit how to
> constraint the type arguments of universal generics.
>
> 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.
>
> regards,
> Rémi
>
> ------------------------------
>
> *From: *"Red IO" <redio.development at gmail.com>
> *To: *"amber-dev" <amber-dev at openjdk.org>
> *Sent: *Wednesday, January 25, 2023 8:03:14 AM
> *Subject: *Constructor Interfaces
>
> Summary
> -------
>
> Enable a parameterized class to constrain the parameterized type to be
> constructible with a given list of parameters.
>
>
>
> Motivation
> ----------
>
> 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:
> Box<String> stringBox = new Box<>(String::new);
>
> 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.
> It also clutters api's like "toArray" which requires an IntFunction to be
> type safe.
>
> Description
> -----------
>
> ConstructorInterface
> 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:
>
> @ConstructorInterface //optional validation like FunctionalInterfaces
> public interface DefaultConstructible {
> new();
> new(char[] chars);
> }
>
> A parameterized type could declare this interface as a type bound for its
> parameter and therefore enabling it to be constructed safely. Like this:
> public class Box<E extends DefaultConstructible> {
> public Box() {
> E newElement = new E();
> }
> }
> The containing type is not forced to implement the ContructorInterface
> explicitly. It is implicitly implemented if the required constructor(s)
> is(are) present.
> public static void main(String[] args) {
> Box<String> stringBox = new Box<>(); //compiles because String has the
> required constructors.
> Box<java.sql.Date> dateBox new Box<>(); error: java.sql.Data does not
> satisfy the type bound DefaultConstructible
> }
> 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.
>
> class Foo implements DefaultConstructable {
> //both required by the interface
> public Foo() {}
> public Foo(char[] chars) {}
> }
>
> class Bar extends Foo {
> //the requirement for the required constructors is passed down.
> public Bar() {}
> public Bar(char[] chars) {}
> }
>
>
>
> public static <T extends Foo> T createT() {
> return new T();
> }
>
> public <T extends Foo> T wrapper() {
> return createT();
> }
> This would technically work but would require a lot of static analysis to
> find the real type of T to call its constructor.
> 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.
>
> Alternatives
> ------------
> 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) :
> public static T foo<T>() where T: new() {
> return new T();
> }
> In java:
> public static <T extends new()> T foo() {
> return new T();
> }
> The downside of this approach is obviously the introduction of new syntax
> rather than reusing the interface/inheritance syntax.
>
> 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.
>
>
>
> Risks and Assumptions
> ---------------------
>
> 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.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230125/4a57d47a/attachment.htm>
More information about the amber-dev
mailing list