Java泛型类继承参数化类型

6
假设有以下现有类:

class A { 
  public void foo() { ... };
  ...
}

class A1 extends A  { ... };
class A2 extends A  { ... };
...
class A1000 extends A  { ... };

现在,我们需要创建每个Axx类的一个变体,覆盖“foo”方法。基本思路是:

class B<T extends A> extends T {
  @Override public void foo () { ... };
}

但似乎不可能从它们参数化的类型中继承一个类。

目标是避免需要遵循以下新代码:

class B1 extends A1 { @Override public void foo() { ... }; }; 
class B2 extends A2 { @Override public void foo() { ... }; }; 
....
class B1000 extends A1000 { @Override public void foo() { ... }; };

并允许类似以下的语句:
... 
B<A643> b643 = new B<A643>; 
b643.foo(); 
...

有什么提示吗?

非常感谢。


2
你的代码中根本没有使用类型参数 T,因此完全可以将其从代码中删除。另外,如果 T 真的是一个形式化的类型参数,那么 B extends T 是无效的。 - scottb
目标是避免需要编写以下新代码:class B1 extends A1 { Override public void foo() { ... }; }; class B2 extends A2 { Override public void foo() { ... }; }; ... class B1000 extends A1000 { Override public void foo() { ... }; };。在问题中进行了澄清。 - pasaba por aqui
我觉得 OP 想做的是用这个 foo 的实现方式来扩展任何给定类型的通用方法。例如,A1A2、...、A1000 是完全(或大部分)不相关的,每个都有自己的方法,而 B1B2、...、B1000 同样是不相关的,每个都具有与其 Annn 对应项相同的方法,以及这个通用的 foo 实现(可能是重写或使用 A 的受保护成员)。 - TheHans255
3个回答

5

A不是通用的。我认为你想要的是像这样的东西,

class B<T> extends A {
  @Override public void foo () { ... };
}

这是一个泛型类型 B,它扩展了A... T extends A 意味着 B 接受一种扩展自 A 的类型(不是 B 扩展自 A)。


嗨,感谢您的合作。目标是跳过编写诸如“class B1 extends A1...”、“class B2 extends A2...”之类的内容,并使用泛型“class B”,如问题所示。通用类是“B”,而“A1”...“A1000”是类型参数。 - pasaba por aqui
@Alu,在Java中这是不可能的。 - Elliott Frisch
仪器化和内省? - pasaba por aqui
不允许您基于参数化类型生成新类。 - Elliott Frisch
通常旧代码无法修改,就像在这种情况下一样。 - pasaba por aqui
显示剩余2条评论

1
你可以将继承与委托混合使用。我认为这样做有点丑陋,但它应该能够正常工作。
class UniversalB extends A{
 A a;
 UniversalB(A a) {
    this.a = a;
 }

 @Override public void foo() { ... };

 // @Override any other method from A you want/need
 // and delegate it to the passed member if necessary

}

UniversalB b = new UniversalB(new A123());
b.foo();
b.anyMethodInA();

嗨,感谢您的合作。您提出的问题在于A123在其原始方法中调用“foo()”时,它将使用A123实现的foo,而不是“UniversalB”中的新实现。 - pasaba por aqui
1
确实如此。但是,创建具有动态、编译时未知层次结构的类是不可能的。模板在编译时进行验证,但据我所记,实际上在运行时被跳过。这是一种代码验证的语法糖。 - Dariusz

0

最终,使用代理类解决了问题。标准的反射代理不适用,但是来自图书馆CGLib的代理可以使用。简而言之,使用与“B.foo”相同代码的拦截器。有关详细信息,请参见覆盖时反射代理无效。感谢Tagir Valeev的帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接