是否可以在不显式强制转换的情况下推断返回类型?

Is it possible to infer the return type without explicit casting?

提问人:Slevin 提问时间:7/12/2023 最后编辑:Mark RotteveelSlevin 更新时间:7/12/2023 访问量:57

问:

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;
        }
    }
}
Java 泛型 转换 类型推理 生成器

评论

0赞 Andy Turner 7/12/2023
不。我怀疑你的意思是“显式”,而不是“隐含”。
0赞 Andy Turner 7/12/2023
或者更确切地说,不,如果你将相同类型的“事物”作为参数传递给 ,并且该事物不涉及 ,你就无法做到这一点。如果可以传入(或类似),则可以返回 .newBuilderTBuilderProvider<T>Builder<T>
0赞 Slevin 7/12/2023
感谢您的回复。我已将标题更改为显式。我将尝试弄清楚如何添加您建议的技术,也许我可以以某种方式将信息作为枚举作为属性传递?
0赞 Honza Zidek 7/12/2023
你想达到什么目的?您的代码在零件周围闻起来。在这里使用一些模式,比如策略或类似的东西,以避免 ing,很可能你的问题会得到解决。switch (template)swith
1赞 Honza Zidek 7/12/2023
使用哪种模式?请阅读: 重构 Java switch 语句的七种方法switch

答: 暂无答案