Given an abstract class "Foo" that has a getter and setter for a "value"
abstract class Foo<T> {
T get value;
set value(T newValue);
}
I'm trying to override getter and setter to make the value final;
with the implementation below
class Bar implements Foo<String> {
@override
final String value;
const Bar(this.value);
}
the linter complains Missing concrete implementation of 'setter Foo.value'.,
but if we add the implementation
class Bar implements Foo<String> {
@override
final String value;
const Bar(this.value);
@override
set value(String newValue) => value = newValue;
}
when we use the setter
void main() {
const bar = Bar('hello');
bar.value = 'world';
print(bar.value);
}
we don't receive ant warning about using the setter for a final value, but at runtime we incur in this error
Uncaught RangeError: Maximum call stack size exceededError: RangeError: Maximum call stack size exceeded
the problem seems to be only for the setter, therefor\
There is no correct way to disable a setter in the base class because doing so is fundamentally incorrect. A derived class must be substitutable for the base class. If the derived class did not provide a setter, then it would no longer be providing the base class's interface and would violate the substitution principle. Consider:
It is not possible to issue any compile-time warnings or errors; the implementation and call of
updateFooare both legal from static analysis.Instead consider:
UnmodifiableListViewdo).Also, your specific exception occurs because of a different mistake in your implementation. When you do:
then the
value = newValue;statement will trigger thevaluesetter again, resulting in infinite recursion as hinted at by the error message. If you instead tried to do:then your
Barimplementation would have generated a compile-time error for trying to reassign_value, which isfinal. And if you made_valuenon-final, then the compiler would have generated a compile-time error telling you thatBarthen could not have aconstconstructor.