简体   繁体   English

如何使用泛型类作为参数并扩展类型?

[英]How to use a generic class as a parameter and extend the type?

I am attempting to use generics in my project to have a base class that can make use of different types of objects. 我试图在我的项目中使用泛型来创建一个可以使用不同类型对象的基类。 But I am having trouble when trying to pass these generic typed classes as parameters in some cases. 但是在某些情况下尝试将这些泛型类型作为参数传递时遇到了麻烦。

So I guess my question is, is there any way to use a certain generic typed interface and pass in extensions of the generic type? 所以我想我的问题是,有没有办法使用某种泛型类型接口并传入泛型类型的扩展?

I am sorry if I am phrasing this strangely, I am not very used to trying to explain these types of questions. 我很抱歉,如果我这样说的很奇怪,我不太习惯于解释这些类型的问题。 I would be glad for some kind of insight into generics, I feel like I can't get a grip on how they really worked. 我会很高兴对仿制药有所了解,我觉得我无法控制它们的真实效果。 I have read many posts about them but I couldn't find any that describe my problem or really help me understand it all. 我已经阅读了很多关于他们的帖子,但我找不到任何描述我的问题或真正帮助我理解这一切的帖子。

I have tried numerous variations on extending the generic type T, also trying to use wildcards. 我已经尝试了许多关于扩展泛型类型T的变体,也试图使用通配符。 But I always just end up with way to many nested generics and captures of wildcards and I just make a mess. 但我总是最终找到许多嵌套的泛型和通配符的捕获,我只是弄得一团糟。

I have this interface: 我有这个界面:

public interface NiceObject<T extends SomeClass> {}

And then I want to be able to extend it with different implementations: 然后我希望能够通过不同的实现扩展它:

public class EpicClass extends SomeClass {}
public class CoolObject implements NiceObject<EpicClass> {}

This works fine for me, but when I attempt to pass an implementation of NiceObject as a parameter of type NiceObject<T> where T is an extension of SomeClass it tells me that the type is not applicable. 这对我来说很好,但是当我尝试将NiceObject的实现作为NiceObject<T>类型的参数传递时,其中T是SomeClass的扩展,它告诉我该类型不适用。

public void coolMethod(NiceObject<SomeClass> obj);
CoolObject obj = new CoolObject();
coolMethod(obj);
// this does not work

I have also tried changing the method in some ways: 我也试过在某些方面改变方法:

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.

EDIT I'll try to make my question a bit clearer: 编辑我会尝试让我的问题更清楚一点:

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>)

What confuses me is that EpicClass is clearly an extension of SomeClass , shouldn't the compiler be able to accept it as a SomeClass because it inherits the same properties as one? 令我困惑的是, EpicClass显然是SomeClass的扩展,编译器是否应该能够接受它作为SomeClass因为它继承了与一个相同的属性?

EDIT 2 It seems like I have resolved my issue now. 编辑2好像我现在已经解决了我的问题。 I have a tendency to solve my problem right after I make a post about it. 在我发布关于它的帖子之后,我倾向于解决我的问题。

As a comment proposed, it was more about the problems it caused in other parts of the program. 正如提出的评论,更多的是它在该计划的其他部分引起的问题。 I didn't want to mix in other parts of my program because the structure of it and my overuse of generics is kind of dumb and I did not want to make it even more confusing. 我不想混淆我的程序的其他部分,因为它的结构和我对泛型的过度使用有点愚蠢,我不想让它更令人困惑。

When I modified the coolMethod() to be able to accept any kind of NiceObject<SomeClass> other problems appeared. 当我修改coolMethod()以便能够接受任何类型的NiceObject<SomeClass>出现其他问题。 I had methods in a NiceObject that had to use it's own type of NiceObject as parameters. 我在NiceObject中有方法必须使用它自己的NiceObject类型作为参数。 I solved it by creating a method that would return itself and subtypes would implement that method. 我通过创建一个返回自身的方法来解决它,子类型将实现该方法。

public interface NiceObjectUser <N extends NiceObjectUser<N>> {
     public N getSelf();
}

I also did other silly things to make the errors disappear and I had to refactor quite a few other classes. 我还做了其他愚蠢的事情来使错误消失,我不得不重构其他几个类。 in the end though, it works so whatever. 最后,它无论如何都有效。

I do appreciate the answer which explained some things about generics which I have now accepted. 我非常感谢能够解释一些我现在已经接受的仿制药的答案。 I now feel like I have a greater level of understanding of generics. 我现在觉得自己对仿制药的理解程度更高。

The issue here is that even though EpicClass is a subtype of SomeClass , NiceObject<EpicClass> is a subtype of NiceObject<SomeClass> . 这里的问题是,即使EpicClassSomeClass的子类型, NiceObject<EpicClass>NiceObject<SomeClass>的子类型。 To see why, consider: 要了解原因,请考虑:

class Box<T> {
  private T value;
  T get() {
    return value;
  }

  void set(T value) {
    this.value = value;
  }
}

Now think of two classes like Object and String , where String is a subtype of Object . 现在想想两个类,比如ObjectString ,其中StringObject的子类型。 Let's say we allowed Box<String> to be a subtype of Box<Object> . 假设我们允许Box<String>Box<Object>的子类型。 That would mean you can use a Box<String> anywhere that was expecting a Box<Object> . 这意味着您可以在任何期望Box<Object>地方使用Box<String> Box<Object> Now think about code like this: 现在考虑这样的代码:

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!

In general, the fact that a box might consume a T or produce a T means that subtyping rules don't work the way you might expect. 通常,框可能消耗 T生成 T这一事实意味着子类型规则不会按预期方式工作。 In general the proposed alternatives you posted are the way to go when you run into a problem like this; 一般而言,当您遇到类似这样的问题时,您发布的建议替代方案是可行的; in order to figure out why they're not working we're going to have to know more about the specifics of what you're trying to do. 为了弄清楚他们为什么不工作,我们将不得不更多地了解你想要做的事情的具体细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM