【发布时间】:2015-05-25 03:49:03
【问题描述】:
考虑以下不可变类:
A
B extends A
C extends B
D extends C
...
A 类有一个名为process 的方法,它获取A 类型的参数,然后返回调用对象类型的值:
public class A {
public final <T extends A> T process(A a) {
Class clazz = getClass();
T result = createObjectOfType(clazz);
return result;
}
}
public class B extends A { }
public class C extends B { }
这是(非常简单的)测试代码:
public void test()
{
A a = new A();
B b = new B();
C c = new C();
// Returns type A:
A resultAAA = a.process(a); // Works.
A resultAAB = a.process(b); // Works.
A resultAAC = a.process(c); // Works.
B resultAAA = a.process(a); // Runtime error.
B resultAAB = a.process(b); // Runtime error.
B resultAAC = a.process(c); // Runtime error.
C resultAAA = a.process(a); // Runtime error.
C resultAAB = a.process(b); // Runtime error.
C resultAAC = a.process(c); // Runtime error.
// Returns type B:
A resultBBA = b.process(a); // Works.
A resultBBB = b.process(b); // Works.
A resultBBC = b.process(c); // Works.
B resultBBA = b.process(a); // Works.
B resultBBB = b.process(b); // Works.
B resultBBC = b.process(c); // Works.
C resultBBA = b.process(a); // Runtime error.
C resultBBB = b.process(b); // Runtime error.
C resultBBC = b.process(c); // Runtime error.
// Returns type C:
A resultCCA = c.process(a); // Works.
A resultCCB = c.process(b); // Works.
A resultCCC = c.process(c); // Works.
B resultCCA = c.process(a); // Works.
B resultCCB = c.process(b); // Works.
B resultCCC = c.process(c); // Works.
C resultCCA = c.process(a); // Works.
C resultCCB = c.process(b); // Works.
C resultCCC = c.process(c); // Works.
}
我想修改源代码,将那些 runtime 错误转换为 compile time 错误或警告,而不必重载或覆盖 process 方法。
但是,client/test 代码不得更改(无强制转换或泛型参数)。
编辑:这个问题没有真正的解决方案。所以我接受了关于覆盖process 方法的明显答案。这是最适合客户端代码的方法,即使它是维护的噩梦。也许有一天可以修改 Java 类型系统,以便可以编写“this 的类型”。然后我们可以写类似public final this process(A a) 的东西。如果您有兴趣,请参阅this page(在 cmets 部分)中的建议。
【问题讨论】:
-
方法
process不使用a。你的意思是a.getClass()? -
@pbabcdefp 不,OP 的真正含义是 A.getClass()、B.getClass() 或 C.getClass(),具体取决于对象的实际运行时类型。
-
只是澄清一下,“没有泛型参数”是指在 trst 代码中的方法调用,还是在类定义上,或其他什么?
-
@marcg 这奇怪地让我想起了实数、整数和自然数...... ;) 你的问题很棘手。您是否考虑过双重调度方法?
-
@Magnamag 是的,这是提出这个问题的更好方法,我从那里链接到这里。关于双重调度,我猜是关于根据对象类型运行不同的代码,但这里的代码是相同的(
process方法的内部结构不会改变)。我只是想找到一种方法让编译器看到c.process(...)返回一个C类型的值,例如。
标签: java hierarchy class-hierarchy generics