web-dev-qa-db-fra.com

Génériques Java - Pourquoi "étend T" est-il autorisé mais pas "implémente T"?

Je me demande s’il existe une raison particulière en Java d’utiliser toujours "extends" plutôt que "implements" pour définir les limites de typeparameters.

Exemple: 

public interface C {}
public class A<B implements C>{} 

est interdit mais 

public class A<B extends C>{} 

est correct. Quelle est la raison de ceci?

272
user120623

Il n'y a pas de différence sémantique dans le langage de contrainte générique selon qu'une classe "implémente" ou "étend". Les possibilités de contrainte sont 'étend' et 'super' - c'est-à-dire que cette classe fonctionne avec assignable à celui-ci ou qu'elle est assignable à partir de celui-ci.

316
Tetsujin no Oni

La réponse est dans ici

Pour déclarer un paramètre de type lié, indiquez le nom du paramètre, suivi du mot clé extends, suivi de sa borne supérieure […]. Notez que, dans ce contexte, étend est utilisé dans un sens général pour signifier soit extends (comme dans les classes), soit implements (comme dans les interfaces).

Donc, voilà, c'est un peu déroutant et Oracle le sait.

53
MikaelF

Probablement parce que pour les deux côtés (B et C), seul le type est pertinent, pas la mise en œuvre. Dans votre exemple

public class A<B extends C>{}

B peut aussi être une interface. "extend" est utilisé pour définir des sous-interfaces ainsi que des sous-classes.

interface IntfSub extends IntfSuper {}
class ClzSub extends ClzSuper {}

Je pense généralement que 'Sub étend Super' en tant que ' Sub est semblable à Super , mais avec des fonctionnalités supplémentaires', et 'Clz implémente Intf' en tant que ' Clz est une réalisation de Intf '. Dans votre exemple, cela correspondrait à:Bressemble àC, mais avec des fonctionnalités supplémentaires. Les capacités sont pertinentes ici, pas la réalisation.

16
beetstra

Il se peut que le type de base soit un paramètre générique, de sorte que le type réel peut être une interface d'une classe. Considérer:

class MyGen<T, U extends T> {

De même, du point de vue du code client, les interfaces sont presque impossibles à distinguer des classes, alors que pour les sous-types, il est important.

7

Voici un exemple plus compliqué où les extensions sont autorisées et éventuellement ce que vous voulez:

public class A<T1 extends Comparable<T1>>

7
ntg

C'est en quelque sorte arbitraire quel terme utiliser. Cela aurait pu être l'un ou l'autre. Peut-être que les concepteurs de langage ont pensé que "étend" était le terme le plus fondamental et "implémentait" le cas particulier des interfaces.

Mais je pense que implements aurait un peu plus de sens. Je pense que cela communique plus que les types de paramètres ne doivent pas nécessairement être dans une relation d'héritage, ils peuvent être dans n'importe quel type de relation de sous-type [].

Le glossaire Java exprime un vue similaire .

5
Lii

Le terme "étend" dans ce contexte, signifie comme les implémentations dans les interfaces et s'étend dans les classes. Voici plus d'explication

1
The_Martian

Nous avons l'habitude de

class ClassTypeA implements InterfaceTypeA {}
class ClassTypeB extends ClassTypeA {}

et toute légère déviation de ces règles nous confond grandement.

La syntaxe d'un type lié est définie comme suit:

TypeBound:
    extends TypeVariable 
    extends ClassOrInterfaceType {AdditionalBound}

( JLS 12> 4.4. Variables de type> TypeBound )

Si nous devions le changer, nous ajouterions sûrement le cas implements

TypeBound:
    extends TypeVariable 
    extends ClassType {AdditionalBound}
    implements InterfaceType {AdditionalBound}

et se retrouver avec deux clauses traitées de manière identique

ClassOrInterfaceType:
    ClassType 
    InterfaceType

( JLS 12> 4.3. Types et valeurs de référence> ClassOrInterfaceType )

sauf que nous aurions également besoin de nous occuper de implements, ce qui compliquerait les choses davantage.

Je crois que c'est la raison principale pour laquelle extends ClassOrInterfaceType est utilisé à la place de extends ClassType et implements InterfaceType - pour que les choses restent simples dans le concept compliqué. Le problème est que nous n'avons pas le bon mot pour couvrir à la fois extends et implements et nous ne voulons absolument pas en introduire un.

<T is ClassTypeA>
<T is InterfaceTypeA>

Bien que extends crée des dégâts quand il s’agit d’une interface, il s’agit d’un terme plus large qui peut être utilisé pour décrire les deux cas. Essayez d’accorder votre esprit au concept de extension d’un type (non prolonger une classe, ne pas implémenter une interface). Vous limitez un paramètre de type par un autre type et le type de ce type importe peu. Il importe seulement que ce soit sa borne supérieure et que c'est son supertype .

1
Andrew Tobilko