我发现自己处于泛型的奇怪情况,到目前为止似乎不可能。我尝试在简单的类中隔离这种情况。我试图完成的是:一个服务类,它调度句柄来处理数据包。每个处理程序都有一个Packet类型参数,因为它应该是每个数据包的处理程序。服务类还有一个Handler类型参数,因为有几种类型的处理程序,因此不同的处理程序类型需要几个服务。这个描述可能不是很清楚,所以这是我做的例子:
.footer_btn {
//Your css
}
.footer_btn:hover {
background-image: url('image.jpg');
}
有没有办法完成这样的事情或任何建议?感谢
编辑:这是来自manouti答案的修改后的代码(注意:为了清楚起见,我将SomePacket更改为PacketOne)。我遇到的问题是创建ServiceImpl的内容。
public abstract class Service<T extends Handler<?>> {
//Some random logic
//If only I could use T<E>
protected abstract <E extends Packet> void handle(T handler, E packet);
}
public class ServiceImpl extends Service<HandlerOne<?>> {
@Override
protected <E extends Packet> void handle(HandlerOne<?> handler, E packet) {
handler.handle("someString", packet); //ERROR
}
}
public interface Handler<E extends Packet> {
}
public interface HandlerOne<E extends Packet> extends Handler<E> {
void handle(Object someObject, E packet);
}
public class HandlerOneImpl implements HandlerOne<SomePacket> {
@Override
public void handle(Object someObject, SomePacket packet) {
}
}
public interface Packet {
}
public class SomePacket implements Packet {
}
答案 0 :(得分:3)
方法handle
需要Object
和E
类型的参数(类型参数)。您只指定了第二个。
然后,即使由于Object
通配符的捕获转换而在第一个参数中引入?
,您仍会收到错误。所以我会选择两个类型参数:
public abstract class Service<E extends Packet, T extends Handler<E>> {
// Some random logic
protected abstract void handle(T handler, E packet);
}
public class ServiceImpl<E extends Packet, T extends HandlerOne<E>> extends Service<E, T> {
@Override
protected void handle(T handler, E packet) {
handler.handle(new Object(), packet); // some object as first parameter
}
}
当前代码的问题在于以下声明:
protected <E extends Packet> void handle(HandlerOne<?> handler, E packet) {
handler.handle("someString", packet); //ERROR
}
你告诉处理程序,它被输入“某种”数据包类型,以处理类型为E
的数据包。在运行时,处理程序的实际数据包类型可能不是E
。
答案 1 :(得分:0)
你正在面对Java Type系统的限制,为了正确地做到这一点,你需要像Higher Kinded Types这样的东西。 Java并不支持这一点,并且与我已经看到的实现最接近的是(实验)项目HighJ中的类型。 HighJ使用Witness类型来分隔容器和值类型。例如,来自wiki。
我发现在Java中模拟高阶类型多态的唯一方法是使用我们已经拥有的抽象,即类型参数的抽象。要做到这一点,我们需要分离&#34;容器类型&#34;从它的值类型,然后使其成为一个类型参数。而不是
List<String> we have something like
Something<List, String>.
然而,在生产(Java)项目中执行此操作可能不是一个好主意,因为它很复杂且学习曲线陡峭。我建议你在某个地方简化你的设计。
更高的Kinded类型(泛型的泛型)允许更高级别的抽象(你可以说
List<T extends Processor<E>>
例如),为了使您的设计更简单,您可以牺牲抽象(在某处复制某些代码),或者键入安全性(动态语言与高级类型系统一样简洁)。
您可以通过额外的单元测试来弥补类型安全性的损失。