I am developing a tool that generates dart code and I am facing this runtime error when executing a program having a circular dependency.
file.dart:xx:xx: Error: Constant evaluation error:
this.b = const B(),,
^
file:xx:xx: Context: Constant expression depends on itself.
this. A = const A(),
Here is a simplification of the program I am executing:
class A {
final B b;
const A({
this.b = const B(),
});
}
class B {
final A a;
const B({
this.a = const A(),
});
}
As you can see there is a circular dependency between A and B.
I tried dropping the const keyword as:
class A {
final B b;
A({
this.b = B(),
});
}
class B {
final A a;
B({
this.a = A(),
});
}
But instead, I am getting a compile time error:
The default value of an optional parameter must be constant. dart(non_constant_default_value)
Do you have an idea how to handle this type of issue? Or is there an equivalent of forwardref in Dart?
Edit
At the current state of dart, it is not possible to avoid this circular dependency. I ended restricting this case. If the input has a circular dependency, it is normal that the output will have it.
2
Answers
How about using factory constructors?
Your approaches don’t work because when you construct
A()
, it will construct aB()
which will constructA()
which will constructB()
, ad infinitum. You need to break the infinite recursion loop.If you want a single instance of
A
and a single instance ofB
to have references to each other, you will need to have one of them pass a reference to itself instead of letting the other constructor create a new instance of the initial type. You can’t passthis
in an initializer list (this
is not yet valid at that point), so it must be done in the constructor body, and the initializedfinal
members will need to belate
. The constructor body also means that both classes cannot haveconst
constructors.If you want
const
constructors because you want to haveA()
andB()
as default arguments, the typical approach is to usenull
as a default.