gpt4 book ai didi

java - 类继承 : generic extends generic

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:58:22 26 4
gpt4 key购买 nike

假设我有一个简单的类

public class MyObject {
}

以及处理MyObject子类的handler接口(interface)

public interface MyObjectHandler<V extends MyObject>{
List<V> handle(List<V> objects);
}

假设,我有 BigObjects 和 SmallObjects(它们都扩展了 MyObject)并且我想为它们设置单独的处理程序。因此,我创建了两个具有特定泛型的 MyObjectHandler 接口(interface)。

class BigObject extends MyObject {}
class SmallObject extends MyObject {}

// Handlers interfaces
interface BigObjectHandler extends MyObjectHandler<BigObject>{}
interface SmallObjectHandler extends MyObjectHandler<SmallObject>{}

// Concrete handlers
class BigHandler1 implements BigObjectHandler {....}
class BigHandler2 implements BigObjectHandler {....}

class SmallHandler1 implements SmallObjectHandler {....}
class SmallHandler2 implements SmallObjectHandler {....}

现在假设我们已经创建了AbstractHandlerChain<...>抽象类。因此,我们可以创建 BigHandlerChain 类并注入(inject)我们的 BigHandler(与 SmallHandlerChain 相同)。

class BigHandlerChain extends AbstractHandlerChain<BigObjectHandler> {
// Inject only childs of BigObjectHandler. E.g. via spring @Autowired
public BigHandlerChain(List<BigObjectHandler> handlers) {
this.handlers = handlers;
}
}

问题:是否有可能为这种情况创建完美的 AbstractHandlerChain?

可能的解决方案1

public abstract class HandlerChain<T extends MyObjectHandler> {

private List<T> handlers;

public HandlerChain(List<T> handlers) {
this.handlers = handlers;
}

public <V extends MyObject> List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}

这个有效,但在 handler.handle(objects)我得到 Unchecked call to 'handle(List<V>)' as a member of raw type 'MyObjectHandler' ,所以我应该添加 @SuppressWarnings("unchecked")那不是很好。

可能的解决方案2

public abstract class HandlerChain<T extends MyObjectHandler<? extends MyObject>> {

...

public <V extends MyObject> List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}

不起作用。在 handler.handle(objects)我得到 handle (java.util.List<capture<? extends MyObject>>) cannot be applied to (java.util.List<V>) .为什么在这种情况下我不能将对象传递给处理程序? Wildcard 扩展了 MyObject,V 扩展了 MyObject。还不够吗?

可能的解决方案3

public abstract class HandlerChain<T extends MyObjectHandler<V>, V extends MyObject> {

...

public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}

这个可行,但在这种情况下,我应该将 BigHandlerChain 定义为 class BigHandlerChain extends AbstractHandlerChain<BigObjectHandler, BigObject> .但是BigObjectHandler已经包含关于类的信息,可以由它处理,所以它是信息重复。

可能的解决方案4

public abstract class HandlerChain<T extends MyObjectHandler<V extends MyObject>> {

...

public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}

这里有一个解决方案,我期望从 java 中得到,但它不起作用!我不能这样声明类 ...class HandlerChain<T extends MyObjectHandler<V extends MyObject> .为什么我在MyObjectHandler后面可以使用通配符,但是不能使用这个构造?

最佳答案

解决方案一

This one works, but in handler.handle(objects) I get Unchecked call to 'handle(List)' as a member of raw type 'MyObjectHandler', so I should add @SuppressWarnings("unchecked") that is not very good.

的确,因为 MyObjectHandler是通用类型,但您没有在 HandlerChain 中指定它的类型的类型参数。

方案二

Doesn't work. In handler.handle(objects) I get handle (java.util.List>) cannot be applied to (java.util.List). Why I can't pass objects to handlers in this case? Wildcard extends MyObject and V extends MyObject. Isn't it enough?

没有。 ? extends MyObject基本上说它是针对一些未指定的类型扩展 MyObject ,但你没有说是哪个。你可以创建一个类 public class BigHandlerChain<BigObjectHandler>但提供 SmallObject 的列表实例到 doChain .

方案三

This one works, but in this case I should define BigHandlerChain as class BigHandlerChain extends AbstractHandlerChain. But BigObjectHandler already contains information about classes, that can be handled by it, so it's information duplication.

确实,这里有一些重复的信息,但是当像这样组合泛型类型时,很可能会发生这种情况。由于您的 doChain方法对某种类型进行操作,必须指定该类型可以做什么。将其视为您将要处理 BigObject列表和您提供的处理程序必须能够处理 BigObjects。

解决方案 4

Here is a solution, that I expect from java, but it doesn't work! I can't declare class like this ...class HandlerChain. Why I can use wildcards after MyObjectHandler, but can't use this construction?

问题是 V指示某种特定类型,而不是通配符,因此您需要指定 V 是什么。

换句话说,尽管有一些重复信息,您的解决方案 3 是正确的方法。不幸的是,您将在 Java 中看到更多此类内容。当字段上的特定修饰符关键字可以达到相同的效果时(就像在 Ruby 中一样),Getters/setters 可以说是不必要的样板文件。

但是请注意,如果您指定 public abstract class HandlerChain<T extends MyObjectHandler<V>, V extends MyObject> ,您将链指定为仅适用于一种特定类型的 MyObjectHandler .由于我认为您可能需要一系列能够处理相同对象类型的不同处理程序,因此您最好只指定该对象类型:

public abstract class HandlerChain<V extends MyObject> {

private List<MyObjectHandler<V>> handlers;

public HandlerChain(List<MyObjectHandler<V>> handlers) {
this.handlers = handlers;
}

public List<V> doChain(List<V> objects) {
for (MyObjectHandler<V> handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}

}

关于java - 类继承 : generic extends generic,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43612264/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com