web-dev-qa-db-fra.com

Implémentation de Comparable avec une classe générique

Je veux définir une classe qui implémente l'interface Comparable générique. Dans ma classe, j'ai également défini un élément de type générique T. Afin d'implémenter l'interface, je délègue la comparaison à T. Voici mon code:

public class Item<T extends Comparable<T>> implements Comparable<Item> {

    private int s;
    private T t;

    public T getT() {
        return t;
    }

    @Override
    public int compareTo(Item o) {
        return getT().compareTo(o.getT());
    }
}

Lorsque j'essaye de le compiler, j'obtiens les informations d'erreur suivantes:

Item.Java:11: error: method compareTo in interface Comparable<T#2> cannot be applied to given types;
        return getT().compareTo(o.getT());
                     ^
  required: T#1
  found: Comparable
  reason: actual argument Comparable cannot be converted to T#1 by method invocation conversion
  where T#1,T#2 are type-variables:
    T#1 extends Comparable<T#1> declared in class Item
    T#2 extends Object declared in interface Comparable
1 error

Quelqu'un peut-il me dire pourquoi et comment y remédier?

13
frank.liu

Item (sans aucun argument de type) est un type brut , donc:

  1. Nous pourrions passer tout type de Item à Item.compareTo. Par exemple, cela compilerait:

    new Item<String>().compareTo(new Item<Integer>())
    
  2. La méthode o.getT() renvoie Comparable au lieu de T, ce qui provoque l'erreur de compilation.

    Dans l'exemple sous le 1er point, après avoir passé Item<Integer> À Item.compareTo, Nous passerions alors par erreur un Integer à String.compareTo. L'erreur de compilation nous empêche d'écrire le code qui fait cela.

Je pense que vous avez juste besoin de supprimer les types bruts:

public class Item<T extends Comparable<T>>
implements Comparable<Item<T>> {

    ...

    @Override
    public int compareTo(Item<T> o) {
        return getT().compareTo(o.getT());
    }
}
18
Radiodef

Vous utilisez des types bruts dans votre définition de classe (Item<T> est générique, mais vous omettez le paramètre de type <T>), remplacez-le par:

class Item<T extends Comparable<T>> implements Comparable<Item<T>>

(Notez le dernier <T>)

La méthode compareTo devra également être modifiée:

public int compareTo(Item<T> o) { // again, use generics
    return getT().compareTo(o.getT());
}
7
Njol

Je pense que cela a plus de sens. J'ai compilé et testé les éléments suivants:

class Item<E extends Comparable<E>> implements Comparable<E> {

 private int s;
 private E t;

 public E getE() {
     return t;
 }

 @Override
 public int compareTo(E e) {
     return getE().compareTo(e);
 }

 public int compareTo(Item<E> other)
    {
        return getE().compareTo(other.getE());
    }

 }

Notez que vous devez maintenant disposer de deux méthodes compareTo.

1
aditya