这是我想要做的:
我有一个接口服务如下:
public interface Service<A extends Object, R extends Object> {
R run(A a);
}
现在,我想链接两个这样的服务,同时保持通用:
public class Link<A, R> implements Service<A, R> {
private Service<A, X> s1; // fail
private Service<X, R> s2; // fail
public <X> Link(Service<A, X> s1, Service<X, R> s2) {
this.s1 = s1;
this.s2 = s2;
}
@Override
public R run(A a) {
return s2.run(s1.run(a));
}
}
我想要解决的问题是将一个泛型类型X分配给类Link,但我希望通过它的构造函数而不是通过类声明来推断它。
如何实现?
编辑:
我解决这个问题的方法是通过实用程序静态方法来完成链接过程:
public static <A, I, R> Service<A, R> link(final Service<A, I> s1, final Service<I, R> s2) {
return new Service<A, R>() {
@Override
public R run(A a) throws Exception {
I intermediate = s1.run(a);
return s2.run(intermediate);
}
};
}
答案 0 :(得分:4)
您不能拥有属于您的类的一般类型X
(不是每次方法调用都重新选择),而不是其声明的一部分。
当然,你可以隐藏不安全的演员,并确保你的程序能够正常工作,但这些只是Java类型系统限制中唯一的两个选择。
但是,我会做的不是提供Link
构造函数,而是提供静态工厂方法
public static <A, X, R> Service<A, R> link(Service<A, X> s1, Service<X, R> s2) {
return new Link<A, X, R>(s1, s2);
}
...确保X
被自动推断并永不逃避。
答案 1 :(得分:0)
这将有效:
public class Link<A, R, X> implements Service<A, R> {
private Service<A, X> s1;
private Service<X, R> s2;
public Link(Service<A, X> s1, Service<X, R> s2) {
this.s1 = s1;
this.s2 = s2;
}
@Override
public R run(A a) {
return s2.run(s1.run(a));
}
}
答案 2 :(得分:0)
为了更好的协方差,您可以像这样调整上述答案:
public class Link <F, X, T> implements Service <F, T> {
private final Service<F, ? extends X> from;
private final Service <X, ? extends T> to;
public Link(Service <F, ? extends X> from, Service <X, ? extends T> to) {
this.from = from;
this.to = to;
}
@Override
public T run (F input) {
return to.run (from.run (input));
}
}