Make constructors of default implementations of the API interfaces public
Akii opened this issue · 3 comments
Is your feature request related to a problem? Please describe.
Currently, all *Impl
classes like AddressImpl
are created with a public empty constructor, and a package-private constructor that has all class properties as parameter. When extending, I cannot call this constructor. Instead I need to call the setters. This is problematic when fields are added because the compiler cannot help me identifying missing fields. I currently also do not understand why this constructor is package-private in the first place.
Describe the solution you'd like
Make all constructors of the default implementation of API interfaces public.
Describe alternatives you've considered
- Calling setters and just hope I catch all changes.
- Not extending the class but implement the interface otherwise. This introduces a bit of complexity in code generation but would actually be safer. If the proposed solution is not possible, I will fall back to that alternative, which is also ok.
Additional context
It's for the library, I want as much help from the compiler as possible :)
As the constructor with parameters is package private we can ensure that adding fields or even reordering them is not a breaking change e.g. reorder fields of the customer class.
If there is a need to extend it should be done either by implementing the interface or another possibility could be to decorating the Impl class.
Good point. I will just go ahead and implement the interface again instead of using inheritance. Thank you!
Your comment made me think through Kotlin delegation again.. and what can I say, it's perfect.
package test.`package`.address
import com.commercetools.api.models.common.Address
import io.vrap.rmf.base.client.utils.Generated
import test.`package`.custom_fields.AddressCustomFieldsType
@Generated
public class TypedAddress(
address: Address,
private val custom: AddressCustomFieldsType?
) : Address by address {
public override fun getCustom(): AddressCustomFieldsType? = this.custom
}
Now all that is left is some minor JSON transformation. It's a bit more tricky for the product types but worth it considering the code generation will be more resilient to changes of the API while maintaining absolute compatibility.
Thanks again.