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

时间:2019-06-06 18:52:22

标签: 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作为实现Template的模板返回?

谢谢!

编辑:实际上,我要实现的工厂看起来像这样,并且似乎这就是围绕类型推断的问题所在:

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进行了很多测试,包括类型检查,因此现在必须这样做。

2 个答案:

答案 0 :(得分:6)

TemplateImpl仅与Template<ChildObject>兼容,因此new TemplateImpl()不能是public <T extends ParentObject> Template<T> generate()的有效返回值-因为T可以是{的另一个子类{1}}

最简单的更改是使ParentObject为一类:

Template

或者,如果必须是接口,则也使private class Template<T extends ParentObject> { void doSomething(T object){/*implement*/} } 通用:

TemplateImpl

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

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>

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

答案 1 :(得分:2)

您的错误是TemplateImpl不是通用的。它已经有一个定义。然后您对generate()方法进行了参数化。 TemplateImpl被迫使用ChildObject,而您的generate()则返回扩展Parent的“内容”。您可以将return语句强制转换为Template。