I would like to perform this in Dart:
abstract class A
{
int f();
}
class A1 extends A
{
@override
int f() => 1515;
}
class A2 extends A
{
@override
int f() => 1789;
}
class X<T extends A> extends T
{
int x() => f();
}
void main()
{
X<A1> x1 = X<A1>();
X<A2> x2 = X<A2>();
print( x1.x() ); // Should print 1515;
print( x2.x() ); // Should print 1789;
}
The critical line is the one defining template class X: the compiler complains because X is inheriting of the template argument (which extends A, so it could know that it is a class).
I may admit that I'm pushing the language a bit far (my C background...) but is there a way to perform this in Dart?
Addendum
I tried this:
abstract class A
{
A();
int f();
}
class A1 extends A
{
A1();
@override
int f() => 1515;
}
class A2 extends A
{
A2();
@override
int f()=>1789;
}
class X<T extends A> {
late T t;
X(){
t = T();
}
int x() => t.f();
}
void main()
{
X<A1> x1 = X<A1>();
X<A2> x2 = X<A2>();
print( x1.x() );
print( x2.x() );
}
But the compiler is now complaining on the line with t = T();...
'T' isn't a function. Try correcting the name to match an existing function, or to define a method or function name 'T'.
CodePudding user response:
Dart has generics, which are similar to but are not the same as C templates. C templates are more similar to macros where template arguments are substituted at compilation time, and it results in separate compiled versions of the template class for each combination of template arguments. Dart generics are different and instead are like Java's: there is a single compiled version of the generic class.
You therefore can't use duck-typing with T
like you would with C , and you can't invoke T
constructors or static
methods.
What you instead can do is to provide a callback that constructs a T
, e.g.:
class X<T extends A> {
T t;
X(T Function() makeT) : t = makeT();
int x() => t.f();
}
void main()
{
X<A1> x1 = X(A1.new);
X<A2> x2 = X(A2.new);
...
}
(I also made X.t
no longer late
(late
is unnecessary if you initialize it via the constructor's initializer list) and removed the explicit type parameters when invoking the X
constructors (they now can be inferred from the argument).)
CodePudding user response:
This a solution even without templates but the concept doesn't match what I am looking for.
- In the question above, X and x are two different kinds of services by themselves.
- In the solution below, X is a service using A1 or A2 as subservice providers.
Voilà:
abstract class A
{
A();
int f();
}
class A1 extends A
{
A1();
@override
int f() => 1515;
}
class A2 extends A
{
A2();
@override
int f()=>1789;
}
class X {
late A t;
X(A x){
t = x;
}
int x() => t.f();
}
void main()
{
X x1 = X(A1());
X x2 = X(A2());
print( x1.x() ); // Indeed prints 1515
print( x2.x() ); // Indeed prints 1789
}