Generic and Comparable in Java

Asked

Viewed 251 times

4

I have a question I can’t get answered, if anyone can give me a plausible explanation I’d be grateful.

Assuming I have two classes:

public class Figura implements Comparable<Figura>
{
    private final int largura, altura;

    Figura(int l, int a)
    {
        largura = l;
        altura = a;
    }

    @Override
    public int compareTo(Figura o) 
    {
        if((o.largura*o.altura) > (this.altura * this.largura))
            return 0;
        else
            return 1;
    }


}


public class Rectangulo extends Figura 
{
    Rectangulo(int altura, int largura)
    {
        super(altura, largura);
    }


}

When I try to create a generic method that allows comparing 2 elements, if do:

 public static <T> int comparaRect(T rect, Comparable<? super T>  outroRect)
 {
     return outroRect.compareTo(rect);
 }

It works without problem. But if it does:

  public static <T> int comparaRect(T rect, Comparable<? super T>  outroRect)
     {
         return rect.compareTo(outroRect);
     }

It no longer works. Getting the error of cannot find Symbol T etc..

My question here is: Why I can only do one way and not both, since one element is inherited from the other and then also inherits the interface comparable Figure?

Thanks in advance.

  • Maybe because there’s no way to know the kind of rect at that time, only at execution time, and already the type of outrorect yes(a Comparable with parameterized supertype).

  • Okay, I understand. But in practice, anyway, even though the compiler doesn’t know when to compile, both 1 and another are correct, right? Interestingly if I add in the inherited class in front of the extends Figure, also a Comparable<Figure>, will already work, but from the syntactic point of view does not make much sense to me since the parent class already has the interface implemented.

  • If the compiler generates error in the second, it is because it is not correct, do not agree?

  • But if I make a Rectangular object and another Figure object and try to do rect.compareTo(figure) and figure.compareTo(rect) will work (I’ve tried it). That is, it just doesn’t work in generic methods because the compiler can’t guarantee that the rect object has the right comparable implemented? (even if it will later have it). ps: I edited my previous reply to add more information.

1 answer

2


My question here is: Why I can only do one way and not both, since one element is inherited from the other and then also inherits the interface comparable Figure?

The problem is unrelated to the inheritance, the problem lies in the way the method was assembled:

public static <T> int comparaRect(T rect, Comparable<? super T>  outroRect) {
   return rect.compareTo(outroRect);
 }

Thus, the compiler cannot guarantee (in a secure way) that T is an instance that implements/contains the method compareTo, the method accepts any object as T rect.

If you want to perform the operation with both arguments, the method must be motorcycle in a different way:

public static <T extends Comparable<T>> int comparaRect(T rect, T outroRect) {
   return outroRect.compareTo(rect);
}

Or:

public static <T extends Comparable<T>> int comparaRect(T rect, T outroRect) {
   return rect.compareTo(outroRect);
}

This way you ensure that the two arguments T implement the interface Comparable.

  • Thank you, that’s what I wanted to clarify effectively. It’s all about the compiler when processing type Erase, knowing what you can and can’t do, although syntactically correct.

Browser other questions tagged

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