Generic, extend to an X or Y

Asked

Viewed 72 times

4

How do I get my generic class to only receive guys who extend X or Y?

Example:

class MinhaClasseGenerica<T extends ClasseX ou ClasseY>

Sorry if you got a little confused, I’m new yet, I can’t explain very well.

  • What kind of things are there in classes X and Y?

2 answers

3

Take a look here.

Java does not allow multiple inheritance. A class cannot extend two classes. You can extend one 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 may be to create a mother class of which your two classes are daughters. You can have a mother class with multiple daughters but not a daughter class with multiple mothers.

  • This does not answer the question. The question was about how to restrict the classes accepted in the template, not about multiple inheritance.

  • 1

    "Java does not admit multiple inheritance, a class cannot andstender two classes" is an answer.

  • @corrected nan ;-)

  • Exactly what @Viníciusgobboa.deOliveira said...

3

That’s not possible, and it doesn’t make sense.

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

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 are the methods that type T has? The answer is that it maybe may possess the methods of X and maybe may possess the methods of Y. But the only methods we know for sure that he possesses will be those who are both in X how much in Y.

Now, in this case the methods that are in X but not in Y or who are in Y but not in X, cannot be used without a cast, and the compiler would be right in issuing a build error if you did this:

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

After all, this method may not exist in the given case reference algumObjeto be a Y instead of a X. It would force you to wear one cast, but if you are forced to use Casts, so there’s no point in using the generic type.

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

class MinhaClasseGenerica<T extends X & Y>

On the other hand, maybe X and Y 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 W which also inherits from Z and it’s not even X and neither Y, but this is inherent in language: inheritance is open. There is no closed inheritance in Java. In fact, the fact that there is no closed inheritance 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 way maybe is to work with enums.

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.