Pourquoi List.remove est-il surchargé tel quel?

Existe-t-il des raisons historiques aux deux List.remove ambiguës.

  • List.remove(int)
  • List.remove(Object)

Cela me semble une conception terrible.
Pour une List cela semble vraiment déroutant.

MODIFIER:

Tout le monde semble assez bien avec ça. Laissez-moi préciser les choses un peu.

Disons que j’ai une List .

 Integer idx = Integer.valueOf(2); list.remove(idx) 

Bien idx soit un object, Java est compilé et supprime l’élément à l’index 2.

Si cela avait été une List , le même code aurait appelé une méthode différente avec un comportement totalement différent.

Ne parlons pas de ce qui arriverait avec les génériques.

J’ai l’impression qu’un comportement différent implique que des noms différents sont une règle précieuse, en particulier dans la même classe.

Tout d’abord:

  • List.remove(int) supprime un élément à l’index spécifié et
  • List.remove(Object) (ou Collection.remove(Object) ) supprime l’élément spécifié .

Je ne sais pas si cela était déjà connu, mais par souci d’exhaustivité, je pensais le mentionner.

Il est important de noter que l’API précède de loin les génériques (et plus important encore) la boxe automatique (l’API Collections a été introduite dans Java 1.2 et la boxe automatique dans Java 5).

Ainsi, quand ils ont conçu l’API pour la première fois, il n’y avait absolument aucun moyen de les confondre. Même si votre List contenait des objects Integer , c’est simple: si vous appelez la méthode avec un type d’argument primitif ( int ), il s’agit de l’index, si vous transmettez un Object (même s’il est Integer ), vous transmettez l’object à retirer.

Certes, ce n’est pas encore la meilleure idée (mais bon nombre d’API Java sont … moins que parfaites), mais les risques de confusion étaient beaucoup plus faibles à l’époque.

Le risque accru de confusion n’existe que depuis que la barrière int / Integer est devenue moins visible grâce à la boxe automatique et au déballage automatique.

Sidenote: une “fonctionnalité” importante de l’API de collections est “des noms abrégés pour les méthodes couramment utilisées”. La précédente “solution” de Vector / Enumeration avait des noms notoirement longs pour des opérations assez communes:

  • Vector.elementAt() vs. List.get()
  • Vector.addElement() vs. Collection.add()
  • Enumeration.hasMoreElements() / nextElement() vs. Iterator.hasNext() / next()
  • Vector.removeElement() vs. Collection.remove()
  • Vector.removeElementAt() vs. List.remove(int)

Et le dernier est où ils sont probablement allés un peu trop loin.

Oui, ce cas précis est souvent cité comme exemple de la façon dont des modifications de langage parfaitement conçues (génériques, auto-sélection) peuvent être combinées entre elles et avec des API existantes pour générer des bogues. En effet, Josh aurait souhaité atsortingbuer différents noms aux méthodes, mais lors de la création de cette interface, il n’était jamais imaginé qu’il puisse exister un conflit quelconque entre un object et un int. Vous pouvez trouver une exploration de ce problème dans Java Puzzlers (Bloch / Gafter).

Quoi, ce n’est pas du tout ambigu. L’un supprime à un index spécifié, l’autre supprime un object partout où il se trouve pour la première fois dans la liste … oO

EDIT – la définition d’une méthode est plus que le nom. Le type et le nombre d’arguments font partie de la définition. Lorsque vous prenez la définition de méthode entière , il n’y a pas d’ambiguïté.

L’un d’eux est pour supprimer de l’index spécifique

L’autre est la suppression d’un object, l’index n’est pas important.

Comment est-ce ambigu? La documentation de chaque méthode me semble claire:

E remove(int index)
Supprime l’élément à la position spécifiée dans cette liste (opération facultative).

boolean remove(Object o)
Supprime la première occurrence dans cette liste de l’élément spécifié (opération facultative). Si cette liste ne contient pas l’élément, il est inchangé.

Ils font deux choses complètement différentes, d’où un besoin pour les deux.