简体   繁体   中英

java generic class extends the generic argument

Short version:

What is the correct syntax to make a class extends its generic argument:

 class A<T> extends T {} // doesn't compile

Long version:

I have a base abstract class (the following code has been shortened just for this post purposes)

abstract class D { 
     abstract void f();
     abstract void g();
}

Then, there is a set of possible combinations for each f() and each g(). The goal is to have all the possible combinations.

One solution is to make for each f_j() a class Fj that extends D and implements the f_j(), then for each g_i() we make a class GiFj which extends Fj and implements g_i(). For example

abstract class F1 extends D {
    @Override
    void f() { /* F1 Work */ }
}
abstract class F2 extends D {
    @Override
    void f() { /* F2 Work */ }
}
class G1F1 extends F1 {
    @Override
    void g() { /* G1 Work */ }
}
class G1F2 extends F2 {
    @Override
    void g() { /* G1 Work : Duplicated Code */ }
}

The problem is that the code for Gi is going to get duplicated many times.

The solution that I want to implement is to regroup all GFi into on generic class

class G1<F extends D> extends F {
    @Override
    void g() { /* G1 work */ }
}

So how to do this in java, or if it is impossible what is the good way to do it

Answer to short version

That is not possible in Java. A compiler needs to know at compile time which methods and fields the superclass of a class has. Thus, a class can only extend a concrete class (possible with type variables), but it cannot extend a type variable on its own.

Answer to long version (which on the surface seems to be unrelated to the short version)

You can use composition to achieve sort of what you want:

class Foo {
    final FDelegate fDelegate;
    final GDelegate gDelegate;

    Foo(FDelegate fDelegate, Delegate gDelegate) {
        this.fDelegate = fDelegate;
        this.gDelegate = gDelegate;
    }

    void f() {
        fDelegate.f(this);
    }

    void g() {
        gDelegate.g(this);
    }
}

interface FDelegate {
    void f(Foo container);
}
interface GDelegate {
    void g(Foo container);
}

Then you have classes F1 , F2 , G1 , G2 which contain the various method implementations. You pass a Foo object so that you can access its (visible) members.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM