补充泛型类型
前提条件:在我的项目中,我有两个分别定义请求和响应的一般类型接口。处理请求以产生响应,因此每个响应都基于请求构建。处理器接口处理请求以构建相应的响应。补充泛型类型
代码:请求和响应接口是:
interface Request<T1>
和
interface Response<T2>
分别
,其中T2
和T1
代表通用请求和响应类型(我故意通过不同调用它们名称为清晰)。
现在,由于T2 是请求,和T1 是响应,因此上述码发展到:
interface Request<T1 extends Response>
和
interface Response<T2 extends Request>
注意的是:请求和响应接口不共享任何继承关系 - 以上代码仅用于进行通信的是:请求仅使用某种其他类型(即响应)进行键入。
现在,考虑请求接口:由于响应被再次输入,并且建立了一种请求的响应将被捆绑到原来的请求类型,因此,上面的代码发展到:
interface Request<T1 extends Response<? extends Request<T1>>>
和现在
interface Response<T2 extends Request<? extends Response<T2>>
,处理器接口被定义为:
interface Processor<R1 extends Request<R2>, R2 extends Response<R1>> {
R2 process(R1 request);
}
具体类:
要求执行:
class ConcreteRequest implements Request<ConcreteResponse> {
ConcreteResponse response;
...`
}
响应实现:
class ConcreteResponse implements Response<ConcreteRequest> {
ConcreteRequest request;
...
}
处理器实现:
class ConcreteProcessor implements Processor<ConcreteRequest, ConcreteResponse> {
ConcreteResponse process(ConcreteRequest request) {
...
}
}
问题:上面的代码是否过度设计?是否有简化的方法来表示补充输入输出对象的元组?
除非我完全误解了你的问题,否则你不会 - 也不应该 - 为这类问题使用泛型。使用多态性和/或组合将会更合适。例如,如果您需要在响应中集成请求的副本(几乎不必要但可以想象),那么您可以在响应类中添加对请求对象的引用。
从技术上讲,可以使用类型定义对Request
对象的引用;然而,你不应该这样做,因为它永远是一个对象(基类或派生子类),而不是某种随着每个响应实例而改变的任意类。
可以使用通用的,当每个被引用对象的类型是完全不同的(例如,一个List <String>
或List<Request>
:有一个String
和Request
物体之间没有子类的关系),或当使用多态性将是不够的因为你正在一个子类中定义一个或多个新的虚函数,这些虚函数不在超类中。
建设Response
是基于一个Request
因为Request
进行处理,以产生Response
绝对不是要走的路和当前Processor
接口是证明了这一点。
谢谢你的答案。我理解你的观点,为什么泛型不适用:泛型类型可能的类型之间没有“子类化关系”,但为什么你认为“建立响应基于请求......绝对不是去...处理器界面是对此的证明。“ - 是否导致任何反模式?如果你可以请解释。谢谢! – Neel
响应将在请求之后构建并发回的事实并不意味着这两者之间存在分层的超类/子类关系。从面向对象的角度来看,响应和请求是属于两个不同类别的两个不同的对象。他们可能会共享一些常见的函数,接口或其他元素(这一切都取决于您的代码),但是您不应该将这些共享元素与函数混淆,回复将作为对请求的答复发回。 – SylvainL
你为什么认为请求和响应共享一个继承关系? (这是来自我的代码片段的暗示吗?如果是这样,我正在更新一个笔记)事实上,我使用组合来保持一个在另一个中的引用。唯一的继承是用Request定义的泛型类型;这意味着请求通常与另一种类型的响应相关联。 – Neel
我想你不需要在类型定义中链接Request
和Response
。他们与Processor
并列。是不是像
interface Requestable {
...
}
class Request<T extends Requestable> {
...
}
class Response<T extends Requestable> {
...
}
class Processor<T extends Requestable> {
Response<T> process(Request<T> request) {
...
}
}
足够?其实我不确定你需要通用。
感谢您的回复。在你的代码片段的上下文中,请求和响应不需要一般地输入。 – Neel
有一个使用案例,它有一个有效的请求/响应(或好,至少是请求)。如果请求泛型包含响应类型,下面的调用是“类型安全”
public <messy define of T> T sendRequest(Request<T> request)
现在,方法的用户会看到“安全类型”请求 - 响应调用。我只是称这只是“类型安全”,因为该方法的实现可能需要将响应转换为T,所以ClassCastException在理论上是可行的,但在大多数情况下,它们将被视为应用程序逻辑错误。
我不会把请求/响应的实际字段放在其他地方,只是使用泛型类型信息来进行“类型安全”的请求 - 响应调用。
对不起,您能解释一下这个吗?'Request'为什么'T1''Request'会扩展'Response'类型? –
vijay
@Vijay:T1不是一个响应,它是泛型类型,它指示它最终会在处理后生成的响应...例如列表意味着一个包含字符串对象作为其元素的列表......是你所询问? –
Neel
通过'Request'和'Response'使用泛型,你会获得什么?一个简单而具体的例子在这里会有很长的路要走。 –