Reputation: 3645
I am having trouble understanding how generics in Dart work and the documentation did not help me sadly.
If I make a class called Checker
that needs to store it's generic params in some way, I could do it this way (since Dart has reified
generics):
class A {}
class B extends A {}
class Checker<T> {
bool test(dynamic a) {
return a is T;
}
}
main() {
print(Checker<A>().runtimeType);
print(Checker<B>().runtimeType);
print(Checker<String>().runtimeType);
print(Checker<A>().test(A()));
print(Checker<A>().test(B()));
print(Checker<A>().test(""));
}
This prints out, just as you would expect:
Checker<A>
Checker<B>
Checker<String>
true
true
false
Here is the issue:
class A {}
class B extends A {}
class Checker<T> {
bool testChecker<C>(Checker<C> a) {
return C is T;
}
}
The output:
false
false
false
It seems like, that two reified generics do not work well with each other.
In Java, this is mostly solved by storing a Class<T>
, which has isAssignableFrom
function that does what it says. In Dart, the Type
is only an empty abstract class, so there is no use in reading/storing the runtimeType
, because there is no function to call on it to check assignability relationships. (Edit.: All classes returned by runtimeType
are of type _Type
, so none of their methods can be called.)
How can I save runtimeType
in Dart?
Upvotes: 3
Views: 1034
Reputation: 71623
If you change testChecker
to return a is Checker<T>;
, would that be enough for you? That would be checking the runtime type of a
, not the static type of it at the call-point. If you want the latter, you can do return new Checker<C>() is Checker<T>;
.
It is correct that you should never use Type
objects for anything like this, so .runtimeType
is not useful.
The reason the example didn't work was that it did return C is T;
. The is
operator takes an object on the left and a type on the right. So, C
is evaluated as an object, which means it evaluates to an object of type Type
. Then it checks whether Type
is a subtype of T
, which it isn't.
You can't compare type variables directly, you have to compare objects to types. One option is to do <C>[] is List<T>
- that is: Check that a ist of C
(object) is-a list of T
(type).
Since I already had a generic class available, I just used Checker<C>() is Checker<T>
instead.
Upvotes: 2