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

jur*_*rym 8 java inference type-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) { }
}
Run Code Online (Sandbox Code Playgroud)

因此,我有一些从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();
    }
}
Run Code Online (Sandbox Code Playgroud)

或在执行此操作时收到“未经检查的分配”警告(代码按预期的方式工作,但是如果我做错了,我宁愿解决它!)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

有人对我如何在没有任何警告的情况下进行这项工作有任何见解吗?如果这是一个简单的类型,我还没有太多使用类型推断。我不明白的是,为什么我不能将TemplateImpl作为实现Template的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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

ern*_*t_k 6

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*/}
}
Run Code Online (Sandbox Code Playgroud)

或者,如果必须是接口,也可以使其TemplateImpl通用:

private class TemplateImpl<T extends ParentObject> implements Template<T> {
    public void doSomething(ChildObject object) { }
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果您只需要确保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>
    }
}
Run Code Online (Sandbox Code Playgroud)

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