-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[FEATURE] Make the @SuperBuilder's *BuilderImpl class public #3791
Comments
Yeah, well, but where is the use case? I don't understand why you'd want to do this. |
I was not accurate enough. In the issue description, it is possible to use abstract builder class with wildcards. abstract class BaseService<B extends Base.BaseBuilder<?, ?>> {
abstract B newBuilder();
}
class DerivedService extends BaseService<Derived.DerivedBuilder<?, ?>> {
public Derived.DerivedBuilder<?, ?> newBuilder() {
return Derived.builder();
}
} But @SuperBuilder
public abstract class Base {
private boolean base;
}
@SuperBuilder
public class Derived extends Base {
}
public abstract class BaseService<B extends Base.BaseBuilder<?, ?>> {
protected abstract B createBuilder();
public B newBuilder() {
return createBuilder()
.base(true);
}
}
public class DerivedService extends BaseService<Derived.DerivedBuilder<?, ?>> {
@Override
protected Derived.DerivedBuilder<?, ?> createBuilder() {
return Derived.builder();
}
} This does not compile with error in BaseService class:
If using recurring generics (this fixes the compilation error in BaseService)
I currently see only one way to fix this by making DerivedBuilderImpl public and using as type argument |
The issue with using |
Here is the way to have deeper inheritance (Base and BaseService are omitted for brevity). @SuperBuilder(builderMethodName = "derivedBuilder")
public class Derived extends Base {
}
@SuperBuilder(builderMethodName = "subDerivedBuilder")
public class SubDerived extends Derived {
}
public abstract class AbstractDerivedService<B extends Derived.DerivedBuilder<?, B>> extends BaseService<B> {
}
public class DerivedService extends AbstractDerivedService<Derived.DerivedBuilderImpl> {
@Override
protected Derived.DerivedBuilderImpl createBuilder() {
return Derived.derivedBuilder();
}
}
public class SubDerivedService extends AbstractDerivedService<SubDerived.SubDerivedBuilderImpl> {
@Override
protected SubDerived.SubDerivedBuilderImpl createBuilder() {
return SubDerived.subDerivedBuilder();
}
}
In fact, it seems unnatural, as we do not really have instances of Animals, we have instances of Cats that we can work with as Animals. I mean, in practice Derived will likely also be abstract, and there will be no final DerivedService in this case. This way there will be no need to have different |
That said, to preserve the compatibility, there can be two builder methods generated @SuperBuilder
public class Derived extends Base {
// This is exactly the same as it is generated now
@Generated
public static DerivedBuilder<?, ?> builder() {
return new DerivedBuilderImpl();
}
// This returns *BuilderImpl, and has name formed from the name of Derived class.
@Generated
public static DerivedBuilderImpl derivedBuilder() {
return new DerivedBuilderImpl();
}
@Generated
public static final class DerivedBuilderImpl extends DerivedBuilder<Derived, DerivedBuilderImpl> {
...
}
} For compatibility, before generating check that custom Alternatively, generate one builder method the same as it is generated now, but make @SuperBuilder
public class Derived extends Base {
// This is exactly the same as it is generated now
@Generated
public static DerivedBuilder<?, ?> builder() {
return new DerivedBuilderImpl();
}
@Generated
public static final class DerivedBuilderImpl extends DerivedBuilder<Derived, DerivedBuilderImpl> {
@Generated
public DerivedBuilderImpl() {
}
...
}
}
public class DerivedService extends BaseService<Derived.DerivedBuilderImpl> {
@Override
protected Derived.DerivedBuilderImpl createBuilder() {
return new Derived.DerivedBuilderImpl();
}
} What do you think? |
Describe the feature
@SuperBuilder's *BuilderImpl class is currently private, and cannot be used as a generic type argument. Making it public will allow to use it in the following way:
Note: this will also allow for
.builder()
to return*BuilderImpl
class instead of*Builder<?, ?>
. This will likely fix issue #3445.Workaround.
The above code will compile if the derived class has customized
.builder()
method, and customized*BuilderImpl
class.The text was updated successfully, but these errors were encountered: