6

Assume the following existing classes:

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

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

now, we need to create a variant of each Axx class that overrides "foo" method. The basic idea was:

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

But it seems is not posible to extend a class from one of their parametized types.

The objective is to skip the need of following new code:

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

and allow statements like:

... 
B<A643> b643 = new B<A643>; 
b643.foo(); 
...

Any hint?

Thanks a lot.

chburd
  • 4,131
  • 28
  • 33
pasaba por aqui
  • 3,446
  • 16
  • 40
  • 2
    Nowhere in your code is the type parameter `T` actually used for anything, hence you could just eliminate it from your code entirely. Also, if `T` really is a formal type parameter, then `B extends T` is not valid. – scottb May 11 '15 at 11:04
  • The objective is to skip the need of following new code: class B1 extends A1 { Override public void foo() { ... }; }; class B2 extends A2 { Override public void foo() { ... }; }; ... class B1000 extends A1000 { Override public void foo() { ... }; };. Clarified on the question. – pasaba por aqui May 11 '15 at 12:11
  • I feel like what OP is trying to do is have a common way to extend any given type with this implementation of `foo`. For instance, `A1`, `A2`, ... `A1000` are completely (or mostly) unrelated and each have their own methods, and `B1`, `B2`, ... `B1000` are similarly unrelated, each having the exact same methods as their `Annn` counterparts *as well as* this common implementation of `foo` (which might or might not be an override or use `A`'s protected members). – TheHans255 Aug 24 '17 at 21:21

3 Answers3

5

A isn't generic. I think you wanted something like,

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

That is a generic type B that extends A... T extends A would mean B takes a type that extends A (not B extends A).

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • Hi, thanks for your colaboration. The objective is to skip the need to write something like "class B1 extends A1...", "class B2 extends A2..." with a generic "class B" like the one show in the question. The generic class is "B" and "A1"..."A1000" are the type parameters. – pasaba por aqui May 11 '15 at 10:52
  • @Alu that isn't possible in java. – Elliott Frisch May 11 '15 at 10:55
  • instrumentation and introspection? – pasaba por aqui May 11 '15 at 10:59
  • Won't allow you to generate new classes based on a parametrized type. – Elliott Frisch May 11 '15 at 11:02
  • Often, problems like this are best solved using the Collections framework API. You may think that you have classes Annn that need to extend Bnnn, but most likely your problem could be refactored to make better use of the things Java is good at: interfaces and classes. – scottb May 11 '15 at 11:10
  • Often old code can not be modified, like in this case. – pasaba por aqui May 11 '15 at 12:04
  • Generics are a compile-time type safety feature, and they are [erased](http://docs.oracle.com/javase/tutorial/java/generics/erasure.html) after compilation. They are not intended for your use case (in fact, Java doesn't have any mechanism to generate `n` extended classes). – Elliott Frisch May 11 '15 at 12:10
1

You can mix inheritance with delegation. I'd consider it ugly, but it should work.

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();
Dariusz
  • 21,561
  • 9
  • 74
  • 114
  • Hi. Thanks for your colaboration. The problem in your proposal is when A123 calls "foo()" in some of its original methods. It will use the A123 implementation of foo, instead of the new one at "UniversalB". – pasaba por aqui May 11 '15 at 12:26
  • 1
    Indeed it is. But it's impossible to create a class which has dynamic, compile-time unknown hierarchy. Templates are verified at compile time, but, as far as I remember, actually practically skipped at runtime. It's kind of a code-verifying syntactic sugar. – Dariusz May 11 '15 at 12:33
0

Finally, solved using a proxy class. Standard reflection.proxy was not applicable, but proxies from librarian CGLib does. In short, an interceptor with the same code than "B.foo" is used. See reflection.proxy not valid when override for details. Thanks to Tagir Valeev for his help.

pasaba por aqui
  • 3,446
  • 16
  • 40