Unlike other languages, Dart allows to override in derived classes any instance
member of a class, including fields.
Overriding a field in a derived class results in a "double storage": the field in the base class is still present, but it is shadowed by the field
in the derived class. So the same name refers to two different storage areas, in two different contexts.
That can lead to confusion and unexpected behavior, because, depending on the context, two completely different values are accessed using the same
name.
class BaseClass {
int field = 0;
void printField() => print(field);
}
class DerivedClass extends BaseClass {
@override int field = 1;
@override void printField() {
print(super.field); // Prints the field from the base class
print(field); // Prints the field from the derived class
}
}
void main() {
BaseClass().printField(); // Prints 0
DerivedClass().printField(); // Prints 0 and 1
}
Moreover, if no explicit way to access to the field is provided in the base class, the derived class would not be able to access the field at all.
This is hardly ever the intended behavior.
More likely, overriding a field was a mistake, often not caught by the developer since the compiler doesn’t enforce the presence of the
@override
annotation.
The rule also applies to mixins, but not to extensions methods or types, since extensions cannot contain instance variable fields.