[英]How to use a generic class as a parameter and extend the type?
我试图在我的项目中使用泛型来创建一个可以使用不同类型对象的基类。 但是在某些情况下尝试将这些泛型类型作为参数传递时遇到了麻烦。
所以我想我的问题是,有没有办法使用某种泛型类型接口并传入泛型类型的扩展?
我很抱歉,如果我这样说的很奇怪,我不太习惯于解释这些类型的问题。 我会很高兴对仿制药有所了解,我觉得我无法控制它们的真实效果。 我已经阅读了很多关于他们的帖子,但我找不到任何描述我的问题或真正帮助我理解这一切的帖子。
我已经尝试了许多关于扩展泛型类型T的变体,也试图使用通配符。 但我总是最终找到许多嵌套的泛型和通配符的捕获,我只是弄得一团糟。
我有这个界面:
public interface NiceObject<T extends SomeClass> {}
然后我希望能够通过不同的实现扩展它:
public class EpicClass extends SomeClass {}
public class CoolObject implements NiceObject<EpicClass> {}
这对我来说很好,但是当我尝试将NiceObject
的实现作为NiceObject<T>
类型的参数传递时,其中T是SomeClass
的扩展,它告诉我该类型不适用。
public void coolMethod(NiceObject<SomeClass> obj);
CoolObject obj = new CoolObject();
coolMethod(obj);
// this does not work
我也试过在某些方面改变方法:
public void coolMethod(NiceObject<?> obj);
public void coolMethod(NiceObject<? extends SomeClass> obj);
public <S extends SomeClass> void coolMethod(NiceObject<S> obj);
// None of these produce my desired result
// I just end up with non-applicable parameters somewhere in my program.
编辑我会尝试让我的问题更清楚一点:
NiceObject<EpicClass> obj = new CoolObject();
coolMethod(obj);
// Message:
// The method coolMethod(NiceObject<SomeClass>) in the type NiceMethods
// is not applicable for the arguments (NiceObject<EpicClass>)
令我困惑的是, EpicClass
显然是SomeClass
的扩展,编译器是否应该能够接受它作为SomeClass
因为它继承了与一个相同的属性?
编辑2好像我现在已经解决了我的问题。 在我发布关于它的帖子之后,我倾向于解决我的问题。
正如提出的评论,更多的是它在该计划的其他部分引起的问题。 我不想混淆我的程序的其他部分,因为它的结构和我对泛型的过度使用有点愚蠢,我不想让它更令人困惑。
当我修改coolMethod()
以便能够接受任何类型的NiceObject<SomeClass>
出现其他问题。 我在NiceObject
中有方法必须使用它自己的NiceObject
类型作为参数。 我通过创建一个返回自身的方法来解决它,子类型将实现该方法。
public interface NiceObjectUser <N extends NiceObjectUser<N>> {
public N getSelf();
}
我还做了其他愚蠢的事情来使错误消失,我不得不重构其他几个类。 最后,它无论如何都有效。
我非常感谢能够解释一些我现在已经接受的仿制药的答案。 我现在觉得自己对仿制药的理解程度更高。
这里的问题是,即使EpicClass
是SomeClass
的子类型, NiceObject<EpicClass>
是NiceObject<SomeClass>
的子类型。 要了解原因,请考虑:
class Box<T> {
private T value;
T get() {
return value;
}
void set(T value) {
this.value = value;
}
}
现在想想两个类,比如Object
和String
,其中String
是Object
的子类型。 假设我们允许Box<String>
是Box<Object>
的子类型。 这意味着您可以在任何期望Box<Object>
地方使用Box<String>
Box<Object>
。 现在考虑这样的代码:
Box<String> stringBox = new Box<String>();
Box<Object> objectBox = stringBox;
objectBox.set(new NonStringObject());
String string = stringBox.get(); // Error! Got a NonStringObject() from a string box!
通常,框可能消耗 T
或生成 T
这一事实意味着子类型规则不会按预期方式工作。 一般而言,当您遇到类似这样的问题时,您发布的建议替代方案是可行的; 为了弄清楚他们为什么不工作,我们将不得不更多地了解你想要做的事情的具体细节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.