-
Notifications
You must be signed in to change notification settings - Fork 245
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
Java - problems implementing class/interface with optional property #543
Comments
In order to work around aws/jsii#543 we now require that anyone who implements IResolvable will implement `creationStack`. Fixes build break on master.
In order to work around aws/jsii#543 we now require that anyone who implements IResolvable will implement `creationStack`. Fixes build break on master.
repro case: adding an optionalString field to the existing
@RomainMuller @eladb It appears that the root cause for this issue is when generating jsii file, the optional properties from the interface are not generated/included in the concrete classes. Is that intentional? If not, I will work on the fix. (I'd expect it generates inherited properties in jsii file) Generated jsii snippets as follows:
|
Looks like the property is not in there because the class doesn't define it. It's probably fine to add it in, but I have no idea what that would do to the rest of the codebase.
Go whichever way suits you. If you decide to with modifying the generated assembly, please make sure the code generated for the other languages also still makes sense. |
FWIW, Looks like there are three options:
I personally prefer option 3. Please let me know what you think or if you have other ideas. |
I think # 1 would work. What are we worried about exactly? |
Maybe nothing. After thinking about it some more, it seems to make sense that classes should have the members listed out, and it shouldn't have any negative consequences. We have to think about the rules though, because (as is usual) inheritance will throw a spanner in the works of naive implementations: interface IParent {
readonly optionalProp?: string;
}
interface ISomething extends IParent { }
class Concrete1 implements ISomething { }
class Concrete2a extends Concrete1 { }
class Concrete2b extends Concrete1 implements ISomething { } In the case of Both in |
Alternatively, we can enforce that implementing classes will define all abstract members explicitly so basically it leaves the edge case resolution to users. That would be my preference. |
Thank you both for your responses! @eladb Do you mean having I actually agree with @rix0rrr It seems a bit odd to me to declare the property in There are also other questions with option 1 if we decide to define all inherited members? do we declare In my opinion, option 3 seems more flexible, because different languages have different inheritance rules and having |
Yes, I mean that jsii will enforce that all abstract fields will always have a concrete implementation in concrete classes. The fact that in typescript you don't have to explicitly implement abstract fields that can be undefined is "sugar" that stems from how javascript works. For all intents and purposes, these fields are defined with the value We had a few cases in the past where jsii reduced some implicit behavior from typescript (one example is how we implemented @internal by enforcing that internal fields will have a "_" prefix) in order to ensure that users are aware of the implications. Bottom line: I think the .jsii spec should reflect that these fields are available on the derived classes. I am okay with doing that implicitly, and also ok with just adding a validation. |
We should generate interfaces w/ default implementations for optional members (that do nothing / return |
Note that while you can opt to not implement an optional interface property, you are required to implement all abstract properties of a parent class (or be abstract): abstract class ExtendMe {
abstract field: string;
}
class DidThat extends ExtendMe {
// TS2515: The non-abstract class 'DidThat' does not implement abstract member 'field' inherited from class 'ExtendMe'
} |
For optional properties on interfaces, emit default implementations when possible (for .NET, this requires `netcoreapp3.0` or later) so that adding a new optional property on an interface does not break existing core that implements the interface. In it's current form, the getters always return `null`, while the setters throw an exception (this may change in the future). Fixes #543
#906) For optional properties on interfaces, emit default implementations (for .NET, this required upgrading the target to `netcoreapp3.0`) so that adding a new optional property on an interface does not break existing code that implements the interface. In it's current form, the getters always return `null`, while the setters throw an exception unless overridden. Fixes #543
When implementing an
abstract class
orinterface
that defines optional properties, but not actually specifying the property (valid in TypeScript), the Java code generator will never emit the concrete implementation of theget
ter, resulting in an invalid class.The text was updated successfully, but these errors were encountered: