Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructing instances of type arguments #3633

Closed
DartBot opened this issue Jun 14, 2012 · 13 comments
Closed

Constructing instances of type arguments #3633

DartBot opened this issue Jun 14, 2012 · 13 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). closed-obsolete Closed as the reported issue is no longer relevant P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug

Comments

@DartBot
Copy link

DartBot commented Jun 14, 2012

This issue was originally filed by @olostan


Currently when compiling such code:

class A {
}

class B<T> {
  T GetBySmth() {
    return new T();
  }
}

void main() {
  var b = new B<A>();
  var x = b.GetBySmth();
  assert(x is B);
}

does not compile with message:

Error: line 6 pos 16: type parameter 'T' cannot be instantiated
    return new T();
               ^

So proposal is to add specifications to inform VM/compiler that generic type does have constructor, so it could be invoked to initialize instance.

Syntax could be (as proposed here https://groups.google.com/a/dartlang.org/d/msg/misc/2vgshmBCZx8/FdI6iKQvEgYJ):

class B<T is new()> {}
class B<T is new(int arg1)> {}

or

class B<T has new(int arg1)> {}

also with named constructors:

class B<T has new.namedConstructor(int arg1)> {}

This will allow to build much more clean generic behaviors (e.g. generic caches, repositories, etc)

@DartBot
Copy link
Author

DartBot commented Jun 14, 2012

This comment was originally written by @olostan


"assert(x is B);" should be "assert(x is A);", of course

@anders-sandholm
Copy link
Contributor

Removed Type-Defect label.
Added Type-Enhancement, Area-Language, Triaged labels.

@gbracha
Copy link
Contributor

gbracha commented Jun 26, 2012

This is non-trivial issue. We've discussed it before, and will again.


Set owner to @gbracha.
Added this to the Later milestone.
Added Accepted label.

@kasperl
Copy link

kasperl commented Jul 10, 2014

Removed this from the Later milestone.
Added Oldschool-Milestone-Later label.

@kasperl
Copy link

kasperl commented Aug 4, 2014

Removed Oldschool-Milestone-Later label.

@gbracha
Copy link
Contributor

gbracha commented Feb 25, 2015

Issue #22424 has been merged into this issue.

@DartBot DartBot added Type-Enhancement area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). labels Feb 25, 2015
@zoechi
Copy link
Contributor

zoechi commented Sep 14, 2015

I guess https://github.com/gbracha/metaclasses/blob/master/proposal.md is supposed to lead to a solution (as reference for people finding this issue first).

@kevmoo kevmoo added P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug and removed accepted labels Feb 29, 2016
@munificent munificent changed the title Initializing from type parameter (Generics) Constructing instances of type arguments Dec 19, 2016
@matanlurey matanlurey added the closed-obsolete Closed as the reported issue is no longer relevant label Jun 19, 2018
@techfan101
Copy link

Still new to Dart and I also ran into this same issue. I see its closed (as obsolete). I also see a link to a proposed solution, but find no action on that proposal.

So, apologies for asking again, but how exactly am I supposed to instantiate a generic type?

@jodinathan
Copy link

Still new to Dart and I also ran into this same issue. I see its closed (as obsolete). I also see a link to a proposed solution, but find no action on that proposal.

So, apologies for asking again, but how exactly am I supposed to instantiate a generic type?

There is the reflectable, json_serializer packages etc

I use source generation

@techfan101
Copy link

@jodinathan Thank you. I appreciate the pointer. Unfortunately, its a bit overkill for my requirements. I've already implemented a quite ugly workaround, but I'm still hoping for a language-supported fix.

@eernstg
Copy link
Member

eernstg commented Mar 17, 2020

@techfan101 wrote:

how exactly am I supposed to instantiate a generic type?

It is basically a questionable idea. However, a solution that will work in general is to pair up the type argument with a corresponding factory function:

class B<T> {
  final T Function() factoryOfT;
  B(this.factoryOfT);
  T getBySmth() => factoryOfT();
}

That factory function may need to embed a lot of decisions. For instance, if T is int then you'd have to return some existing integer rather than a "new" one; if T is a class that only has constructors that take many arguments and require some serious building effort in order to obtain an object that will actually work, then the factory function will have to perform that building work. If T is the empty type (Never) then the factory may be forced to throw an exception or loop forever: There is no way to satisfy the request "give me an element from the empty set".

C# allows for a constraint on type parameters that they must support new(), which is basically syntactic sugar for (1) requiring that the type argument denotes a class that has a constructor that accepts the empty argument list, and (2) passing a factory function around (or using a heterogeneous compilation strategy such that we get a fresh copy of the whole class for each distinct value of the type argument). This kind of syntactic sugar might be convenient in some situations, but it isn't very general. The solution where we declare the factory function explicitly is more general (e.g., it could take whatever parameters we'd want, and we could use different factory functions for different instances of the enclosing class).

@jodinathan
Copy link

@techfan101 wrote:

how exactly am I supposed to instantiate a generic type?

It is basically a questionable idea. However, a solution that will work in general is to pair up the type argument with a corresponding factory function:

class B<T> {
  final T Function() factoryOfT;
  B(this.factoryOfT);
  T getBySmth() => factoryOfT();
}

That factory function may need to embed a lot of decisions. For instance, if T is int then you'd have to return some existing integer rather than a "new" one; if T is a class that only has constructors that take many arguments and require some serious building effort in order to obtain an object that will actually work, then the factory function will have to perform that building work. If T is the empty type (Never) then the factory may be forced to throw an exception or loop forever: There is no way to satisfy the request "give me an element from the empty set".

C# allows for a constraint on type parameters that they must support new(), which is basically syntactic sugar for (1) requiring that the type argument denotes a class that has a constructor that accepts the empty argument list, and (2) passing a factory function around (or using a heterogeneous compilation strategy such that we get a fresh copy of the whole class for each distinct value of the type argument). This kind of syntactic sugar might be convenient in some situations, but it isn't very general. The solution where we declare the factory function explicitly is more general (e.g., it could take whatever parameters we'd want, and we could use different factory functions for different instances of the enclosing class).

The syntactic sugar of C# is convenient in a lot of cases, if not most of them. And it does not stops you from using a factory function explicitly if needed.
I am guessing that you usually needs T() with business models and they are also usually have empty constructors. Our projects all use source generated generic factories with no argument, so a simple T() would have been nice.

@techfan101
Copy link

@eernstg Thank you, but unfortunately your suggestion is a non-starter for my requirements.

@jodinathan Exactly what I need. I am completely comfortable requiring a default/parameterless constructor. While I have the occasional gripe, I think the new() constraint from C# (or some similar syntactic clue) strikes the right balance between convenience and insanity.

Short of some support within the language, I am reluctant to believe that other solutions will truly suffice. Honestly open to suggestions, but I need something broadly applicable that requires little additional plumbing.

I've been at this (engineering not Dart :)) for over 35 years. I can always find ugly workarounds, which is (sadly) what I'm currently using. That said, given that no "good" solution seems apparent, I'm a bit surprised this issue was closed.

copybara-service bot pushed a commit that referenced this issue Nov 7, 2022
Changes:
```
> git log --format="%C(auto) %h %s" 6506cc0..65c7f3e
 https://dart.googlesource.com/pub.git/+/65c7f3e5 Only analyze lib, test and bin an pubspec.yaml on publish (#3630)
 https://dart.googlesource.com/pub.git/+/cbae02df Workaround to allow using local git submodules in tests (#3633)
 https://dart.googlesource.com/pub.git/+/d9077a57 Fix BODY_MIGHT_COMPLETE_NORMALLY_CATCH_ERROR lint (#3631)

```

Diff: https://dart.googlesource.com/pub.git/+/6506cc01b1bd17aff782037817d86a88a1c312e8~..65c7f3e528f3f9978c4330cbd471070f17370f65/
Change-Id: I9ac246761ea775752b102182d1d014a77ab6eec6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/268280
Reviewed-by: Jonas Jensen <jonasfj@google.com>
Commit-Queue: Sigurd Meldgaard <sigurdm@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). closed-obsolete Closed as the reported issue is no longer relevant P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

10 participants