-
Notifications
You must be signed in to change notification settings - Fork 213
A variable declaration used only for interface purposes has unwanted semantics #44
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
Is this a common problem? Most of the time I see interfaces only declare a getter. When a getter and a setter are both provided and abstract, it's usually the case in my experience that the setter is going to need to do work (e.g. mark the object as dirty), such that you wouldn't actually override them with a field anyway. |
It certainly occurs. Strong mode originally disallowed virtual field overrides (this situation), and there was code rejected buy that. Probably wouldn't be too hard to get some data on the frequency. |
A little related there's a similar issue for |
@Hixie wrote:
Of course, the counterpart #45 is just a tiny convenience feature that we've had on the table for a while, but the benefit that it does provide is that it allows abstract classes that need to declare a getter/setter pair to be more concise, and that would still be true even if there won't ever be a subclass that overrides this pair with a field. |
When trying out the NNBD DartPad preview today, I realized that it's not possible to declare non-nullable fields with the field-based syntax as-is. Using the example in the issue description, trying to declare abstract class A {
int x; // error: Non-nullable instance field 'x' must be initialized
} Using abstract class {
late int x;
} It would be really nice if it could just be declared abstract instead 😄. I've wanted something like #45 for a while now to improve our code generation for https://github.com/Workiva/over_react, which also experiences this issue. We generate implementations of user-authored classes that override fields, similar to the example in the description: mixin FooProps on UiProps {
String foo;
}
// .g.dart
mixin $FooPropsImpl on FooProps {
@override
String get foo => props['foo'];
@override
set foo(String value) => props['foo'] = value;
} |
You can do: int get x;
set x(int value); ...to declare it abstract. |
Yeah, the main issue with that, as the end paragraph of the issue description notes, is that it's a bit verbose/redundant. In the OverReact use case, there are many of these properties, and they can change a lot during the course of development. So, having a syntax that's as terse as possible is important to maintain a good user experience when authoring the properties. That's ultimately why we settled on fields over abstract getters/setters, even though it creates an unused field. |
A proposal for this feature, allowing |
This is an edge-case, but: It works fine (besides the inability to have final properties), but the syntax is kinda bad due to this: class Example extends Record {
Example() {
a = 42;
}
int get a;
set a(int a);
}
// OR
class Example extends Record implements _Example {
Example() {
a = 42;
}
}
class _Example {
int a;
} Having to declare both a getter and a setter makes it not very readable. It's obviously an edge-case/temporary workaround, but being able to declare an abstract field would make this use-case a lot better |
Handled according to #44 in Dart today. |
[Handled according to #44 in Dart today.]
Consider the following declaration, where we wish to specify a class that has a property
x
which is intended to be implemented differently in different subtypes:This design makes it possible for subclasses (and other subtypes) to override both the getter and the setter with a simple
int x;
, in the case where the desired implementation is just a simple storage location:But why wouldn't we simply declare the property as
int x;
in the abstract superclassA
and rely on the implicitly induced getter and setter with exactly the same signatures?Assume that the appropriate relationship is
extends
because we wish to inherit the implementation of some other methods.We could then not use a plain
int x;
inA
, because that would incur a subtle memory leak in subclasses where the desired implementation is more complex:Instances of
B2
would now (where we consider anA
that usesint x;
) have storage for a variable corresponding toA.x
, and that storage would we wasted unless some (surely unnatural and confusing) occurrences ofsuper.x
were added here and there to make use of it.So there may be good reasons to declare an abstract getter and setter in order to allow subclasses to make their own choices about how to implement the given property.
The problem is that this is more verbose, and it requires certain parts of the declaration to be redundant and consistent: The name needs to be the same in the getter and the setter, and the return type of the getter needs to be at least related to the argument type of the setter (and they should be the same type almost without exception).
The text was updated successfully, but these errors were encountered: