-
Notifications
You must be signed in to change notification settings - Fork 211
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
Enhanced Default Constructors #698
Comments
The field has an initializer, so it's not included in the constructor: Foo(): super(); It's a good question, though, whether a late final field with no initializer should be included. I'd say no. |
It will require adaption, yes. This is not an attempt to solve all problems. Anything deviating from the simple case will have to be handled manually, just like now. Having a default value for one parameter is possible with the current design: class ColorPoint {
final int x, y;
final Color color;
default ColorPoint({this.color = Color.black});
} This class will allow you to initialize the color, or choose a default value, and you still get automatic default-initialization of Whether The Adding a way to control the order gets too complicated for me. If you are going to write the parameter names anyway, then you can just write them as parameters directly. |
@g5becks Yes, it doesn't solve every issue, but it does introduce a shorter syntax for the constructor part of the issue. |
This would be a huge improvement for immutable architecture (and the upcoming non-nullable types). Would this come as part of NNBD, or is this still negotiated (and potentially need more 👍)? |
It would come after NNBD. The language process is sort of pipelined where we are starting talking about and designing features while the implementation teams are working on previous features. |
Property should be automatically created when mentioned as a parameter in constructor, so that we don't have same thing at 2 place. |
I've updated the proposal (now version 0.4) so that:
|
I just went through the 0.4 proposal. Since it's already landed I'm adding my feedback here. I hope that's OK. :) Bigger suggestions/feedbackWhere to put
|
About allowing One, quite severe, problem is that positional parameters must have required parameters before optional ones. For private fields, it is annoying that they won't work as named, but should work fine as positional. |
Yeah, I agree with you in principle but the empirical observation of #1080 is that most constructors take positional parameters, so if we want this feature to be maximally useful, we should at least support that if not default to it.
Good point. Maybe the safest option is to just support some way to make all of the fields required and positional.
Yes, as magical as it sounds to strip off the
That would be so useful. I can't count the number of times I've had to do |
I'd like to provide some perspective from Rust, since this gets us very close to Rust's struct syntax. For Rust, the initialization syntax matches the syntax used to declare the struct: struct Pair(i32, i32);
struct Triangle {
pos: [Vec2f; 3],
color: [Vec3f; 3],
}
Pair(123, 456);
Triangle {
pos: [Vec2f::ZERO, Vec2f::ZERO, Vec2f::ZERO],
color: [Color::RED, Color::GREEN, Color::BLUE],
} For simple structs (Rectangles, Points, new-types, etc.) you'd use the positional syntax. For more complex objects, you'd use the named syntax. One thing to note is that Rust's positional syntax does not permit field naming (which imo is a huge oversight). Positional syntax gets extremely confusing when your data is non-homogeneous, and the struct name isn't descriptive enough (e.g. Furthermore, some constructors are ambiguous when using positional syntax. Without optionally named constructor parameters, defaulting to named parameters for a first implementation seems the most permissive, because it allows developers to get an initialization syntax that is field-ordering agnostic, while giving an escape hatch that allows one to declare a purely positional constructor (as long as they guarantee that fields won't be reordered in source code later). Also hoping that redirecting constructors are supported, so this is possible: class Rect {
final double left, top, right, bottom;
Rect.ltrb(default);
Rect.xywh(double x, double y, double width, double height) : this.ltrb(x, y, x + width, y + height);
} |
class Foo extends Bar {
Foo({
expand fields as { this.name = default, }
expand super.fields as { type name = default, }
}) : super(expand Bar.fields as { name: name, });
fields {
int a = 0,
String b = '',
Baz c = const Baz(),
}
expand fields as { final type name; }
void copyWith({
expand fields as { type name, },
expand super.fields as { type name, }
}) {
return Foo(
expand fields as { name: name ?? this.name, },
expand super.fields as { name: name ?? this.name, },
);
}
bool operator ==(Object other) {
if (other.runtimeType != runtimeType)
return false;
return (other is Foo) expand fields as { && name == other.name }
&& this super.== other;
}
int get hashCode => hashValues(expand fields as { name, } super.hashCode);
} |
I believe the default constructor should also allow for const. That is this: abstract class SetUserLocationState {
const SetUserLocationState();
}
class Loading extends SetUserLocationState {
const Loading();
} would be equal to this abstract class SetUserLocationState { }
class Loading extends SetUserLocationState { } I don't think this would be a breaking change since you need to specify on the call site if you need Maybe going a step further, all constructors should allow const. |
Allowing If the author never considered whether it should have one (they didn't write one), then they now can't modify the class and add something like: static int _idCounter = 0;
final _id;
SetUserLocationState() : _id = _idCounter++; That would break users using the class in a way the original author didn't intend, but also didn't prevent. That's why we want you to opt in to supporting We can't let all constructors allow |
In that case would some sugar syntax be viable ? const class Something {} // can be instantiated as `const Something() |
Using It must obviously be possible to have such a constructor, so superclass must have const unnamed constructor and class must not have any non-final fields or fields without constant initializers. That restricts the usefullness of the class a lot, and likely means that the feature won't be useful very often. With enhanced default constructors, the restrictions wouldn't be that bad, and it would make more sense to allow |
I propose to have default constructors
This is a solution to #314 (allows you to declare classes with fields without having to write a constructor) and to #469 (forwards superclass constructor parameters). It might even be a solution for some parts of #367, but only in the simple cases where you don't need to do anything except storing the non-forwarded parameters.
(Initial design document).
The text was updated successfully, but these errors were encountered: