-
Notifications
You must be signed in to change notification settings - Fork 1.7k
overridden_fields documentation is vague #58311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Overriding a field with another field is rarely the thing you want to do because it means the object has two storage locations for what is effectively one property. Overriding a field with a getter or setter which calls the super-getter/setter and then does something more, that's completely reasonable. So is overriding a getter/setter pair with another getter/setter, and unless the subclass is in the same library as the superclass, it shouldn't even know whether the superclass uses a field with implicit getter/setter or an explicit getter/setter declaration. Whether something is a fields is an implementation details, it should be able to change from version to version of a package without anyone noticing. Blindly warning about overriding a field, but not a getter, breaks this abstraction. (If it's possible to detect that a field is overridden and unreachable, and it's declared in the same library, then there might be a good reason to give a warning, because you're in position to actually do something about it. Anything other than that is risking false positives.) |
Thank you both for the post. @lrhn I came across this discussion after coming up with this idea, and getting the lint rule. class Product {
Product({required this.sku});
final String sku;
}
class CustomProduct extends Product {
CustomProduct({required Product product, required String customSku}) : sku =
customSku, super(sku: product.sku);
@override
final String sku;
Product get parent => Product(sku: super.sku);
} The real example is more complicated and has more fields, and methods, but the idea is that my Thank yo again |
I'd probably prefer composition over inheritance, so: class CustomProduct extends Product {
final Product parent;
CustomProduct({required Product product, required String customSku})
: parent = product,
super(sku: customSku);
} This way there is no overriding the Alternatively, if you really want to store the parent SKU instead of the parent object, I'd do: class CustomProduct extends Product {
final String _parentSku;
CustomProduct({required Product product, required String customSku})
: _parentSku = product.sku,
super(sku: customSku);
Product get parent => Product(sku: _parentSku);
} Either is easier to read than the unnecessarily overriden You generally never need to override a field with another field. Overriding with a getter/setter with side effects makes sense. Overriding a final field with a mutable field makes a kind of sense, but feels icky, I'd probably prefer reimplementing the interface instead. |
Here's something I tried to do at least a couple of times: class A {
String field = "A generic default initial value for field.";
}
class B extends A {
@override
String field = "An initial value that makes more sense for the subclass.";
} For what it's worth, I didn't care about To avoid the lint, which I never fully understood until now, I learned to do the following: class A {
late String field = fieldDefault;
String get fieldDefault => "A generic default initial value for field.";
}
class B extends A {
@override
String get fieldDefault => "An initial value that makes more sense for the subclass.";
} (I realize I could do it in the constructor without introducing a new getter, but that can make the classes a bit harder to maintain, imho.) Anyway, I just thought I'd add this point. Maybe I'm the only one who wrongly assumed that overriding a field like this is just giving it a different initial value in the subclass. If not, does it make sense to mention this misconception in the lint warning? |
Yes, it makes sense to mention it. Thanks for pointing this out. |
https://dart-lang.github.io/linter/lints/overridden_fields.html states:
If
@override
is used, it quite clearly is not unintentional.Why is it a bad practice to do so? It would be nice to provide examples. #57764 provides some arguments. However, I don't fully buy some of them.
Are we also saying that overriding
get
andset
functions from a base class also is bad? What about overriding a base class field withget
andset
functions?The text was updated successfully, but these errors were encountered: