尝试用 Java 构建可扩展的数据对象和适配器模式
我正在尝试使用适配器模式构建 SDK。这是我到目前为止所得到的:
interface Adapter<T> {
void doWork(WorkUnit<T> unit);
Class<T> getT();
}
class WorkUnit<T> {
public int getId() { ... }
public T getExtras() { ... }
}
class OldWorkUnit {
public <T> void setExtra(T data) { /* Store data in Map<Class, Object> */ }
public <T> WorkUnit<T> toNewWorkUnit(Adapter<T> adapter) { /* Map.get(adapter.getT()) */ }
}
那里有大量的泛型,但我在编译时无法知道 T,并且可能有多个适配器,所有适配器都具有不同类型的 T。这是要暴露给第三方,所以我在接口实现中也需要尽可能少的实现,并且它必须是一个接口(没有抽象类)。
现在我想用它来调用 doWork 和 WorkUnit。我的第一遍代码如下所示:
class FooAdapter implements Adapter<FooWorkUnit> {
...
}
OldWorkUnit w = new OldWorkUnit();
w.setExtra(new FooWorkUnit());
Adapter<?> a = new FooAdapter();
WorkUnit<?> unit = w.toNewWorkUnit(a);
a.doWork(unit);
呃哦,这无法编译:
The method doWork(WorkUnit<capture#2-of ?>) in the type Adapter<capture#2-of ?>
is not applicable for the arguments (WorkUnit<capture#4-of ?>)
我知道 WorkUnit 泛型参数与 Adapter.doWork() 泛型参数的类型相同,但不知道我无法转换的类型适当地。
那么有什么办法可以解决这个问题吗?
I'm trying to build an SDK using an adapter pattern. Here's what I've got so far:
interface Adapter<T> {
void doWork(WorkUnit<T> unit);
Class<T> getT();
}
class WorkUnit<T> {
public int getId() { ... }
public T getExtras() { ... }
}
class OldWorkUnit {
public <T> void setExtra(T data) { /* Store data in Map<Class, Object> */ }
public <T> WorkUnit<T> toNewWorkUnit(Adapter<T> adapter) { /* Map.get(adapter.getT()) */ }
}
There's a good amount of generics in there, but I can't know T at compile time, and there may be multiple Adapters, all with different types of T. This is meant to be exposed to third parties, so I also need as little implementation as possible in the interface implementation, and it has to be an interface (no abstract class).
Now I want to take this and call doWork with a WorkUnit. My first pass at the code looks like this:
class FooAdapter implements Adapter<FooWorkUnit> {
...
}
OldWorkUnit w = new OldWorkUnit();
w.setExtra(new FooWorkUnit());
Adapter<?> a = new FooAdapter();
WorkUnit<?> unit = w.toNewWorkUnit(a);
a.doWork(unit);
Uh oh, that doesn't compile:
The method doWork(WorkUnit<capture#2-of ?>) in the type Adapter<capture#2-of ?>
is not applicable for the arguments (WorkUnit<capture#4-of ?>)
I know that the WorkUnit generic argument is the same type as the Adapter.doWork() generic argument, but without knowing the type I can't cast it appropriately.
So is there a way to work my way through this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为什么你在这里使用通配符模板类?:
如果你这样做:
这不会保留你需要的东西吗?
现在编译器知道 FooWorkUnit 是公分母,可以这么说。
编辑:关于运行时可变性的观点是正确的。如何对执行该工作的方法进行强类型化,以便消除通配符,但仍然保持一致:
Why do you wildcard the template class here?:
If you do this:
Doesn't that preserve what you need?
Now the compiler knows that
FooWorkUnit
is the common denominator, so to speak.Edit: OK point taken about the runtime variability. How about strongly-typing the method that does the work, so that the wildcards are eliminated, but still consistent: