Because the syntax to indicate that a parameter of a generic class is comparable is T extends ComparableT?

5

I've been looking at different posts about the same question but I do not understand why in the syntax <T extends Comparable<T>> you put the word extends and not the word implements , if Comparable is an interface, the argument of the class generic should not implement the Comparable interface instead of extending it? for example if I have an interface A and a normal class B , if I try to write the definition of the class B , B extends A I will have a compile error because A is not a class but is a interface and should change extends by implements , because in this case there is that compilation problem but when you put the parameter T you have to extend the interface Comparable<T> there is no problem?

PS: What's more, if you type <T implements Comparable<T>> I'll have a compilation error.

    
asked by Angelixus 31.10.2018 в 00:03
source

1 answer

6

Because it does not mean the same as in the definition of a class.

When viewing any keyword you have to keep in mind that the context is important . Many keywords have different meanings depending on where they apply.

For example, final in a class indicates that you can not inherit from that class; in a method that a subclass can not redefine the method and in a variable whose value can not be modified. Although in all three cases you can see a certain "semantic affinity" of the keyword with its use, there are three well-defined cases.

So, when you have

public class MiThread<T extends Comparable<T>> extends Thread {

The two extends are different

  • extends Thread indicates that MiThread will fulfill the contract of Thread and inherit the implementation of its methods . Here we define the class, so it is important to know where the methods are obtained 1

  • <T extends Comparable<T>> only means that T will fulfill the Comparable<T> contract. If that is done by inheriting the implementation or implementing its methods, is something internal to the implementation of T . A MiThread is only interested in knowing that, due to this definition, you can do

    public void miFuncion(T t1, T t2) {
       if (t1.compare(t2)) {
          ...
    

    and how the compare will work

In fact, this last extends is only part of what is called bounded types (limited types) and that includes several options that are not available or work differently than in the first extends :

  • multiple extends . When defining the class, it can only be extended from one superclass. Here that is not necessary (for the reasons already explained above):

    <T extends Comparable<T> & Serializable & Number>
    
  • wildcards with upper limit:

    <? extends Serializable> --> "Cualquier objeto que extienda/implemente Serializable, pero sin saber cuál es su clase"
    
  • wildcards with lower limit (note that here also super is reused with another meaning):

    <? super Integer> --> "Cualquier objeto de una de las superclases de 'Integer'"
    

TL; DR Although the two extends mean similar meanings, they are used to represent different things. The people of Sun could have perfectly decided to use another keyword <T supercalifragilísticoespialidoso Serializable> , and everything would work the same. However, they decided to use extends because the meaning is easier to identify.

1 It could be said that all superclasses and interfaces could have been defined by extends and that the compiler give an error if there was more than one class. But nevertheless:
  • makes the difference between classes and interfaces more visible.

  • This was done already since the first version of Java in which the compiler was much more basic.

answered by 31.10.2018 / 01:26
source