Generic, extend to an X or Y

4

How do I make my generic class only receive types that extend from class X or Y?

Example:

class MinhaClasseGenerica<T extends ClasseX ou ClasseY>

Sorry if it got a bit confusing, I'm a newbie yet, I can not explain very well.

    
asked by anonymous 18.04.2015 / 00:26

2 answers

3

This is not possible, nor does it make sense.

The reason is how MinhaClasseGenerica would be used. In this class, T could appear as a return type of a method, a parameter, or the type of a field.

Let's suppose it appears as the return of a method:

public T metodoQualquer() {
    // ...
    return algumObjeto;
}

And I want to use this method:

public void outroMetodo() {
    T algumObjeto = metodoQualquer();
    // Aqui invoca algum método sobre T.
}

What methods does T have? The answer is that may have methods of X and maybe may have Y methods. But the only methods that we know for sure it will have will be those that are both X and Y .

Now, in this case, methods that are X but not Y or that are Y but not X , can not be used without a cast and the compiler would be right to issue a compile error if you did this:

public void outroMetodo() {
    T algumObjeto = metodoQualquer();
    algumObjeto.metodoQueSoExisteNoX();
}

After all, this method may not exist in the given reference case algumObjeto is a Y instead of a X . This would force you to use a cast , but if you are forced to use casts , then you have no reason to use the generic type.

Maybe what you want is that T has the methods of X and of Y instead of the methods of X or % with%. In this case you can declare the following:

class MinhaClasseGenerica<T extends X & Y>

On the other hand, maybe Y and X have something in common. In this case the ideal would be to do the following:

interface Z {
    // Aqui vai o que há de comum entre X e Y.
}

interface X extends Z {
    // Aqui vai o que há em X, mas não em Y.
}

interface Y extends Z {
    // Aqui vai o que há em Y, mas não em X.
}

class MinhaClasseGenerica<T extends Z> {
    // ...
}

That would solve your problem. It would still allow me to invent a Y that also inherits from W and is neither Z nor X , but this is inherent in the language: inheritance is open. There is no inheritance closed in Java. By the way, the fact that there is no inheritance closed in Java allows me to do this:

// Isso não é Exception e nem Error, mas eu posso dar throw nele!
class WTF extends Throwable {}

If what you want is something closed, the path might be to work with Y .

Finally, it is always worth remembering that java does not have multiple class inheritance, and therefore a enums where both <T extends X & Y> and X are classes are forbidden by language. At least one of the two should be an interface.

    
18.04.2015 / 01:34
3

Take a look at here .

Java does not support multiple inheritance. A class can not extend two classes. You can extend a class and multiple interfaces. For example:

public class GenericsTest {

    class Vehicle { }

    interface PassengerVehicle { }
    interface MotorVehicle { }

    // Classe genérica que compila sem problemas
    class ParkingGarage<X extends Vehicle & MotorVehicle & PassengerVehicle>{}


    // Vamos criar uma segunda classe
    class Vehicle2 { }
    // Não compila porque X não pode estender duas classes ao mesmo tempo
    class ParkingGarage2<X extends Vehicle & Vehicle2 >{}
}

The solution to your problem might be to create a parent class for which your two classes are daughters. You may have a multi-daughters mother class, but not a daughter class with multiple mothers.

    
18.04.2015 / 01:34