提问人:Slevin 提问时间:7/12/2023 最后编辑:Mark RotteveelSlevin 更新时间:7/12/2023 访问量:57
是否可以在不显式强制转换的情况下推断返回类型?
Is it possible to infer the return type without explicit casting?
问:
Joshua Bloch 在他的著作 Effective Java 中描述了一种使用比萨饼的构建器模式。我稍微简化了示例,而不是直接实例化构建器,而是想根据枚举值获取相应的构建器:
public static <T extends Person.Builder<T>> T newBuilder(Template template) {
return (T) switch (template) {
case FRIEND -> new Friend.Builder();
case STRANGER -> null;
};
}
不切实际的是,我必须正确转换构建器才能访问子类化方法。但是,即使不强制转换,也可以访问抽象基类的方法:
// works with implicit casting to Friend.Builder
Friend.Builder friendBuilder = newBuilder(Template.FRIEND);
friendBuilder.setNickname("friend");
// works without explicit casting: setDescription (from base class) is accessible
newBuilder(Template.FRIEND).setDescription("very friendly");
// doesn't work without explicit casting: setNickname (from subclass) is not accessible
newBuilder(Template.FRIEND).setNickname("friend");
有没有机会推断返回类型(或在 switch 语句中以某种方式强制转换选定的构建器),以便我可以直接使用子类中的方法,而不必强制转换返回的构建器?
这里涉及三个类的全部内容:
PersonService(主):
public class PersonService {
public static void main(String[] args) {
// works with implicit casting to Friend.Builder
Friend.Builder friendBuilder = newBuilder(Template.FRIEND);
friendBuilder.setNickname("friend");
// works without explicit casting: setDescription (from base class) is accessible
newBuilder(Template.FRIEND).setDescription("very friendly");
// doesn't work without explicit casting: setNickname (from subclass) is not accessible
newBuilder(Template.FRIEND).setNickname("friend");
}
public static <T extends Person.Builder<T>> T newBuilder(Template template) {
return (T) switch (template) {
case FRIEND -> new Friend.Builder();
case STRANGER -> null;
};
}
}
人:
public abstract class Person {
private final String description;
protected Person(Builder<?> builder) {
this.description = builder.description;
}
static abstract class Builder<T extends Builder<T>> {
private String description;
public T setDescription(String description) {
this.description = description;
return self();
}
public abstract Person build();
protected abstract T self();
}
public enum Template { STRANGER, FRIEND }
}
朋友:
public class Friend extends Person {
public Friend(Builder builder) {
super(builder);
}
public static class Builder extends Person.Builder<Builder> {
private String nickname;
public void setNickname(String nickname) {
this.nickname = nickname;
}
@Override
public Friend build() {
return new Friend(this);
}
@Override
protected Builder self() {
return this;
}
}
}
答: 暂无答案
评论
newBuilder
T
BuilderProvider<T>
Builder<T>
switch (template)
swith
switch