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
Specify the behavior for an augmented constructor with no body #3555
Comments
I wouldn't say that For constant generative constructors, you have to write Still, constructor bodies are not like normal function bodies, they're more distanced from the parameters, Which suggests that, fx, calling class A {
final int x, y;
A(int y) : y = log("A.y", y), super() { print("A.body"); }
}
augment class A {
A() : x = log("AugA.x", 1), augmented(log("AugA.super", 2) { print("AugA.body"); }
}
void main() {
new A();
}
T log<T>(String text, T value) {
print(text);
return value;
} would print: "AugA.x", "AugA.super", "A.y", "A.body", and "AugA.body". A non-redirecting generative constructor augmentation can
Which means you can write Or syntactically: class A {
A(params1) : init1 {body1} // no super
}
augment class A {
A(params2) : init2, augment(args1), super(args2) {body2}
} would work (kind-of) like rewritten to: class A {
A(params2) : this._$(params2, args1);
A(params2, params1) : init2, init1, super(args2) { body1; body2; }
} or as an example: class A extends S {
final int x, y, z, w;
A(this.z, int w) : this.w = w { print("A1"); }
}
augment class A {
A(this.x, int y) : this.y = y, augment(x + 1, y + 1), super.name(42) { print("A2"); }
} would be (kind-of) equivalent to: class A extends S {
final int x, y, z, w;
A(int x, int y) : this._$(x, y, x+1, y + 1);
A(this.x, int y, this.z, int w): this.y = y, this.w = w, super.name(42) { print("A1"); print("A2"); }
} |
I see where you are going with that for sure. I worry a bit that the semantics around Also, we don't generally allow changing parameters of functions through augmentation. I think you could argue that this isn't happening in this case, but especially with the initializing formals it does feel like you are altering it to me, because while the type signature might not be changing, the meaning definitely is. If I see |
In fact, in your example, the constructor a user sees looks like it is initializing |
True. In my example, the new constructor is more like a replacements, that calls the original somehow. Augmentations have ... two? three? ... modes of operation:
If a constructor is declared as It could make sense to be allowed to add at least one of:
(The forwarder is mutually exclusive with initializer list and body, and These are all incremental and backwards compatible. Anything you think you can do based on the original declaration, should still work. It would be nice to be able to add It should be possible to keep adding things that are not incompatible with what already exists. More initialize list entries, more optional parameters. Add things that you can have more than one of. But not more bodies, which is where the "modifying" comes in.
All of these can work (mostly) without breaking what you can already do with the previous version of the constructor. |
Yes, but also I think it is good if all parameters you can pass are clearly documented by the original signature. This is partly why we don't allow adding optional parameters to functions generally (although that is also not fully backwards compatible due to overrides for methods). Even though it would be fully safe (I think) in this case, outside of some very esoteric cases involving function type inference, I don't like the idea of adding parameters generally. It is just too surprising. I feel similarly about |
The way augmentations are currently specified, I agree that anything that changes what you can and cannot do with a declaration is not a good fit. So no adding That leaves:
Calling the existing body from a wrapper should probably be I'd also want to add default values of optional parameters that don't have any, or maybe even change existing ones, since the new body might want different defaults. (But it's probably better to just use nullable parameters, and introduce the default value yourself, then that's moot.) I do think that an initial declaration of And |
My main concern is that if there is an existing body, filling in
Yeah, I think this is the only real sensible option for augmenting the constructor body. It feels a bit weird, but makes sense. |
Specifically, given this original class:
And the augmentation:
What is the resulting constructor body? #3554 is also relevant here.
It could be any of these, or possibly others:
;
.The text was updated successfully, but these errors were encountered: