Je me demande s'il y a une raison particulière en Java pour utiliser toujours " extends
" plutôt que " implements
" pour définir les limites des paramètres.
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?
java
generics
syntax
design-choices
user120623
la source
la source
implements
?" - "Parce qu'il n'y a queextends
".implements
n'apporterait rien de nouveau et compliquerait les choses. J'espère que cela vous sera utile.Réponses:
Il n'y a pas de différence sémantique dans le langage de contrainte générique entre le fait qu'une classe «implémente» ou «étend». Les possibilités de contraintes sont «étend» et «super» - c'est-à-dire, est-ce que cette classe fonctionne avec assignable à cette autre (étend), ou est-ce que cette classe peut être assignée à partir de celle-là (super).
la source
class Generic<RenderableT extends Renderable implements Draggable, Droppable, ...> { Generic(RenderableT toDrag) { x = (Draggable)toDrag; } }
veuille compiler des vérifications de temps.La réponse est ici :
Alors voilà, c'est un peu déroutant, et Oracle le sait.
la source
getFoo(List<? super Foo> fooList)
fonctionne UNIQUEMENT avec la classe qui est littéralement étendue par Foo likeclass Foo extends WildcardClass
. Dans ce cas, uneList<WildcardClass>
entrée serait acceptable. Cependant, toute classe quiFoo
implémente ne fonctionneraitclass Foo implements NonWorkingWildcardClass
pas ne signifie pasList<NonWorkingWildcardClass>
qu'elle sera valide dans legetFoo(List<? super Foo> fooList)
. Clair comme de l'eau de roche!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
B peut également être une interface. "extend" est utilisé pour définir les sous-interfaces ainsi que les sous-classes.
Je pense généralement à «Sub étend Super» comme « Sub est comme Super , mais avec des capacités supplémentaires», et «Clz implémente Intf» car « Clz est une réalisation d' Intf ». Dans votre exemple, cela correspondrait à: B est comme C , mais avec des capacités supplémentaires. Les capacités sont pertinentes ici, pas la réalisation.
la source
Il se peut que le type de base soit un paramètre générique, donc le type réel peut être une interface d'une classe. Considérer:
Du point de vue du code client, les interfaces sont presque indiscernables des classes, alors que pour le sous-type, c'est important.
la source
Voici un exemple plus complexe où les extensions sont autorisées et éventuellement ce que vous voulez:
public class A<T1 extends Comparable<T1>>
la source
C'est une sorte d'arbitraire parmi les termes à utiliser. Cela aurait pu être de toute façon. Peut-être que les concepteurs de langage pensaient que «s'étend» comme terme le plus fondamental et «implémente» comme cas particulier pour les interfaces.
Mais je pense que ce
implements
serait un peu plus logique. Je pense que cela communique davantage 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 une vue similaire .
la source
Nous avons l'habitude de
et toute légère déviation de ces règles nous déroute beaucoup.
La syntaxe d'une limite de type est définie comme
( JLS 12> 4.4. Variables de type>
TypeBound
)Si nous devions le changer, nous ajouterions sûrement le
implements
caset se retrouver avec deux clauses traitées de manière identique
( JLS 12> 4.3. Types et valeurs de référence>
ClassOrInterfaceType
)sauf qu'il faudrait aussi s'en occuper
implements
, ce qui compliquerait encore les choses.Je crois que c'est la principale raison pour laquelle
extends ClassOrInterfaceType
on utilise au lieu deextends ClassType
etimplements InterfaceType
- pour garder les choses simples dans le concept compliqué. Le problème est que nous n'avons pas le mot juste pour couvrir à la foisextends
etimplements
nous ne voulons certainement pas introduire un.<T is ClassTypeA>
<T is InterfaceTypeA>
Bien qu'il
extends
apporte un peu de désordre lorsqu'il accompagne une interface, c'est un terme plus large et il peut être utilisé pour décrire les deux cas. Essayez de régler votre esprit sur le concept d' extension d'un type (pas d'extension d'une classe, pas d'implémentation d'une interface). Vous limitez un paramètre de type par un autre type et peu importe ce que ce type est réellement. Il importe seulement que ce soit sa limite supérieure et son super-type .la source
En fait, lorsque vous utilisez une interface générique, le mot clé est également étendu . Voici l'exemple de code:
Il existe 2 classes qui implémentent l'interface Greeting:
Et le code de test:
la source