I'm implementing a Flutter plugin for the Android library and I'm facing the problem.
I have the next Java code:
Data Module
public <T> IDataStore<T> of( Class<T> entityClass )
IDataStore:
T save( T entity )
So i can call:
of(MyClass.class).save(objectOfMyClass)
I want to implement the same method with dart and save the method signature.
As I understand, in Java the generic type is defined by the argument type.
And in Dart the generic method syntax looks like:
T method<T>( T argument )
and generic type is defined by the method type that is specified right after the method name in the angle brackets.
It is way different how generics work in Java and Dart.
For now I can only implement such Dart code:
IDataStore<T> of<T>()
...
T save( T entity )
And call:
of<MyClass>().save(objectOfMyClass)
The question is: can I recognize the generic type from argument, save the same semantic as Java and call
of(MyClass).save(objectOfMyClass)
from dart?
In short: No, not without using dart:mirrors.
The reason is that there is no generic Class class in Dart matching the one in Java.
In Java, the Class type reflects on a class type, like the Type class does in Dart, but in Java, the Class type is generic, so the "runtime type" of an integer is Class<int>.
In Dart, the Type object is not generic, so there is nothing at the type level distinguishing the Type for int from the Type for String. As such, you cannot use the Type object to affect the static typing of the save method.
If you want to look similar to the Java code, I'd go for of<type>().save(object).
However, it's worth noticing that Java erases generics at runtime. The T type parameter only exists at compile-time. Dart keeps the type parameters at run-time, which means that we can use it. That is the reason Java is forced to pass around Class objects instead of just relying on the type parameters. Java uses the generic Class class to allow you to couple generics (erased static types) and Class objects (retained run-time type representations). Dart doesn't need that, you can, and should, use type parameters for both.
So, if all you want to do is a quick save, you can introduce a shorthand:
T saveData<T>(T object) => of<T>().save(object);
which can be used simply as saveData(someObject).
(But notice that inferred type arguments are based on the static type, not the run-time type, of the argument, so you may want to write saveData<MyType>(someSubtypeOfMyType)).
Thank you so much, @lrhn for your help and such detailed explanation!
I agree with you. Given the dart language specifications, it makes sense to use:
of<type>().save(object);
I will use this solution in my project.
Thanks again! :relaxed:
Most helpful comment
In short: No, not without using
dart:mirrors.The reason is that there is no generic
Classclass in Dart matching the one in Java.In Java, the
Classtype reflects on a class type, like theTypeclass does in Dart, but in Java, theClasstype is generic, so the "runtime type" of an integer isClass<int>.In Dart, the
Typeobject is not generic, so there is nothing at the type level distinguishing theTypeforintfrom theTypeforString. As such, you cannot use theTypeobject to affect the static typing of thesavemethod.If you want to look similar to the Java code, I'd go for
of<type>().save(object).However, it's worth noticing that Java erases generics at runtime. The
Ttype parameter only exists at compile-time. Dart keeps the type parameters at run-time, which means that we can use it. That is the reason Java is forced to pass aroundClassobjects instead of just relying on the type parameters. Java uses the genericClassclass to allow you to couple generics (erased static types) andClassobjects (retained run-time type representations). Dart doesn't need that, you can, and should, use type parameters for both.So, if all you want to do is a quick save, you can introduce a shorthand:
which can be used simply as
saveData(someObject).(But notice that inferred type arguments are based on the static type, not the run-time type, of the argument, so you may want to write
saveData<MyType>(someSubtypeOfMyType)).