我正在为我的大学做一个项目,但遇到了问题。
基本上,该项目由一个客户端-服务器应用程序组成,我想为通信创建一个Packet类。该数据包由标题和正文组成。现在有问题了。我可以有一些不同的主体,但是它们都继承了泛型类Body。
我的想法是制作一个这样的Packet类:
public class Packet <T extends Body>{
private Header header;
private T body;
}
和这样的Header类:
public class Header {
private OPS op;
}
现在,我想拥有一种工厂,当我从服务器的主体调用方法Factory.createPacket()时,它将以这种方式构建Packet:
例如,如果读取标头上的CREATE(一种OPS)操作,则应读取CreateBody(继承Body)
此外,每个主体都必须具有允许从SocketChannel获取该类型的主体的功能,这就是我认为使用泛型的原因。
有人可以告诉我更好的方法吗?
谢谢大家!
答案 0 :(得分:1)
不确定您是否真的要在此处使用泛型。如果您全力以赴,这只会对您有所帮助。如果走这条路,您的最终目标应该是依靠编译器来检测何时将某些Header
与错误的Body
类型混合使用。这意味着Header
也应参数化。
您的Header
最终是决定Body
类型的人。由于它嵌入了这些知识,因此最好是将这些信息实际提供给类型系统,即Header<T extends Body>
。
要使其正常工作,您需要基于T
实例,从标题中找出此类型OPS
。因此OPS
本身就必须是参数化类型。
如果OPS
是enum
,则无法对其进行参数化,因此无法以类型安全的方式进行操作(即,在某些时候没有显式强制转换);所以您必须添加类似的方法:
Class<? extends Body> bodyType();
因此,每个OPS
实例都将在内部绑定到主体类型(但是您不能这样使它可见)。有人需要将其转换为特定的身体类型。那可能就是您的Header
:
class Header<T extends Body> {
private final Class<T> bodyType;
public Header(OPS ops) {
// any type-safety feeling gets blown here!
this.bodyType = (Class<T>) ops.bodyType();
}
// ...
}
确保其安全的唯一方法是将OPS
本身参数化为OPS<T extends Body>
并手动实例化每种OPS类型(因为枚举不支持此操作)。
如果这看起来很麻烦,那是故意的。它的主要目的是阻止您使用泛型,因为我猜您真的不需要它们。为了验证这一点,请在代码中寻找任何声明为Packet<SpecificBodyType>
的引用,如果仅仅是Packet
就无法使用。
鉴于您可以将任何Body
子类型视为顶级Body
抽象,因此OPS
可以(内部)绑定到特定的Body
子类。如上所述:Class<? extends Body> bodyType();
。因此,您可以在实际需要的地方在运行时使用特定的类 。
或者,OPS
可以是Function<SocketChannel, Body>
,因此它将自行决定在每个Body
实现中使用哪种apply()
子类型。但是,如果满足以下条件,则程序中的其他任何人都不必关心具体的Body
子类型:
OPS
类型和主体类型之间的链接,供编译器检查。