Java:返回一个实现具有类型推断的接口(interface)的类

标签 java type-inference inference

第一次发帖,标题很垃圾。 我正在尝试使用类型推断,但在使用工厂模式时很难让它正常工作,让我写一些代码来让它更清楚一点:

private class ParentObject { }

private class ChildObject extends ParentObject { }

private interface Template<T extends ParentObject> {
    void doSomething(T object);
}

private class TemplateImpl implements Template<ChildObject> {
    public void doSomething(ChildObject object) { }
}

所以我有一些继承自 Template 的类,这些类对继承自 ParentObject 的对象执行某些操作(我在本文中只发布了其中一个)。 现在我遇到的这个问题是,当我尝试生成这些模板类之一时,我在尝试执行此操作时不断收到“不兼容类型”错误:

private class Factory {
    public <T extends ParentObject> Template<T> generate() {
        return new TemplateImpl(); // here is the error
    }
}
private class Service {
    public <T extends ParentObject> void magic() {
        Factory f = new Factory();
        Template<T> a = f.generate();
    }
}

或者当我这样做时,我收到“未检查的分配”警告(代码按预期工作,但如果我做错了什么,我宁愿修复它!):

private class AlternativeFactory {
    public Template generate() {
        return new TemplateImpl();
    }
}
private class Service {
    public <T extends ParentObject> void magic() {
        AlternativeFactory af = new AlternativeFactory();
        Template<T> b = af.generate(); // warning here
    }
}

有没有人知道我如何在没有任何警告的情况下完成这项工作?如果这是一个简单的类型推理,我还没有使用太多,所以很抱歉! 我不明白的是为什么我不能将 TemplateImpl 作为模板返回,因为它实现了模板?

谢谢!

编辑:事实上,我想要实现的工厂看起来像这样,而且似乎这就是类型推断存在的问题:

private class Factory {
    public Template<T extends ParentObject> generate(int option) {
        switch (option) {
            case 1:
                return new TemplateA(); // implements Template<A> where A extends ParentObject
            case 2:
                return new TemplateB(); // implements Template<B> where B extends ParentObject
            default:
                throw new IllegalArgumentException();
        }
    }
}

编辑:决定使用我上面提供的代码 (AlternativeFactory),并在调用工厂的服务方法中使用 SuppressWarnings,因为看起来我希望实现的目标是不可能的。我知道这使用原始类型并且是不好的做法,但我对这些 Template 对象和 AlternativeFactory 进行了很多测试,包括类型检查,所以现在必须这样做。

最佳答案

TemplateImpl仅与 Template<ChildObject> 兼容, 所以 new TemplateImpl()不能是 public <T extends ParentObject> Template<T> generate() 的有效返回值- 因为 T可以是 ParentObject 的不同子类

最简单的更改是制作 Template一个类:

private class Template<T extends ParentObject> {
    void doSomething(T object){/*implement*/}
}

或者,如果它必须是一个接口(interface),则生成 TemplateImpl也通用:

private class TemplateImpl<T extends ParentObject> implements Template<T> {
    public void doSomething(ChildObject object) { }
}

这将允许您的工厂使用类型参数:

private class Factory {
    public <T extends ParentObject> Template<T> generate() {
        return new TemplateImpl<T>(); //T is not bound to ChildObject
    }
}

如果您只需要确保TemplateImpl仅适用于 Template<ChildObject> ,那么你的工厂方法不需要是通用的:

private class TemplateImpl implements Template<ChildObject> {
    public void doSomething(ChildObject object) { }
}

//and the factory:
private class Factory {
    public Template<ChildObject> generate() {
        return new TemplateImpl(); //TemplateImpl is a Template<ChildObject>
    }
}

应避免使用第二种解决方案,因为它使用原始类型。

关于Java:返回一个实现具有类型推断的接口(interface)的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56483486/

相关文章:

java - 前端实例小时数 Google App Engine

java - 字符串生成器与字符串连接

rust - 为什么 Rust 不能做更复杂的类型推断?

machine-learning - 迭代条件模式 E 步骤 EM

r - 如何在 R 中测试非参数同时推理

Tensorflow - 推理时间评估

java - 为什么 MouseDown 事件的坐标与 MenuDetect 事件的坐标不同?

java - 与原始数据类型范围相关的问题

typescript - 如何使幻像类型与 TypeScript 中的方法一起使用?

Scala:用于转换字符串的通用函数