11
votes

Les génériques Java restreignent à l'interface


8 commentaires

Non, ce n'est pas possible.


Cela me donne un visage triste :(


D'autre part, si vous voulez une chose axée sur la réflexion, vous pouvez simplement passer un class et appeler explicitement class.isinterface () .


@Louiswasserman Il a déjà une instance d'un paramètre. Il peut obtenir la classe à partir de cela. Il n'a pas besoin d'un autre paramètre.


Est-ce que soméclass a quelque chose à voir avec le détail de la création de B ? Si oui, vous devez corréler soméclass à A ou B et refacteur à une signature plus propre. Si non, vous pouvez simplement utiliser Static public B maqueb (une chose) {...} .


Il y a en fait plusieurs soméclass 's, afin de parler. Je dois générer quatre ou cinq classes différentes qui mettent tous l'outil A mais avoir des interfaces de base différentes - elles font tous des choses fondamentalement différentes.


Je pense que le problème ici est de retourner un B à partir de cette méthode. Vous passez B en tant que paramètre de type, mais il n'apparaît jamais nulle part ailleurs dans la signature de la méthode. Comment le compilateur est-il censé inférer le type de retour des arguments ???? On dirait que vous devriez renvoyer un Someclass ou un A . L'un ou l'autre peut être un B sous la hotte, mais doit apparaître sous la forme d'un Someclass ou un A sur le code client.


@jahroy Désolé, je n'ai pas eu la chance de voir votre commentaire à moi avant de supprimer votre réponse. Votre point sur inférer B est absolument raison - j'ai mentionné en fait une préoccupation similaire dans la modification à ma réponse. Vous devriez certainement définir votre réponse parce que c'est utile.


3 Réponses :


1
votes

si soméclass est toujours une classe, le A in ne peut être que Une interface, car il n'y a pas de héritage multiple dans Java. Le seul moyen & a peut être satisfait est si a est une interface.


5 commentaires

Vous pourriez être négligé, mais le compilateur se plaint: le type A n'est pas une interface; Il ne peut pas être spécifié comme paramètre délimité


@jahroy et @ejp Vous semblez avoir à négliger que A est un paramètre de type dans , c'est pourquoi cela ne compile pas.


Ouais ... tu as raison ... mais il n'ya aucun moyen de dire au compilateur que l'argument générique sera une interface?


@ Zoltánnagy c'est le point . si l'argument de type réel fourni sous forme a n'est pas une interface que le compilateur se plaint.


@ Zoltánnagy - Le point de générique est d'obtenir le compilateur pour vous aider à appliquer la sécurité de type. Si vous souhaitez A pour être une interface et que le compilateur se plaint quand il n'est pas, les génériques font leur travail.



1
votes

Je pense que le problème ici est que vous souhaitez renvoyer un B à partir de cette méthode.

Vous spécifiez B comme paramètre de type, mais il n'apparaît jamais nulle part ailleurs dans la signature de la méthode.

Comment le compilateur est-il censé inférer le type de retour des arguments ????

Il n'y a aucune possibilité pour le code client de spécifier ce que B est.

Il semble que vous puissiez revenir à un Someclass ou un A .

L'un ou l'autre peut être un B sous la hotte, mais doit apparaître sous forme de soméclass ou un A sur le code client.


0 commentaires

5
votes

Il est impossible d'imposer une telle restriction de la compilation. Les paramètres de type générique sont des stands pour les types de référence; Ils ne distinguent aucune distinction entre les types de classe et les types d'interface. Le fait que des limites supplémentaires dans la déclaration de paramètre de type devaient être des types d'interface sont simplement accessoires - votre stratégie visant à exploiter cela comme moyen d'imposer un type comme une interface était intelligente, mais il est vaincu par la limitation qui tapez les paramètres n'est pas utilisé dans plusieurs limites .

Vos seules options sont à régler pour une vérification d'exécution à l'aide de classe.isinterface () code> comme Louis wassserman SOITIONNED , ou pour laisser à l'appelant pour être responsable de ce qu'elle passe. De toute façon, veillez à documenter clairement les attentes et le comportement de la méthode. P >


B code> est destiné à être un espace réservé pour une carte générique, de sorte que le client puisse obtenir un seul objet qui est à la fois un soméclass code> et un A code> sans avoir à faire casting en fonction de la confiance. Le client n'aura pas accès au nom de la classe actuelle qui implémente soméclass code> et a code> p> BlockQuote>

Cela semble être une contradiction pour moi. Il ne sert à rien de déclarer B code> si l'appelant ne peut pas savoir ce qu'il évalue. N'oubliez pas: l'appelant d'une méthode générique fournit ses arguments de type. Donc, un appelant décidant b code> sans rien pour la baser sur ne peut être que deviner - et qui ne peut jamais être sécurisé de type. P>

Il semble que vous voulez vraiment que votre méthode redevienne est un type qui est à la fois un soméclass code> et un A code>, mais cela est délicat car ils ne partagent pas de superype commun: p> xxx Pré>

(c'est Syntaxe non sensible a> à des fins de démonstration uniquement) p>

comme solution de contournement, envisagez de remplacer les moyens de représenter à la fois un type Someclass code> et un type d'interface. Par exemple, les interfaces candidates pourraient avoir une méthode courante pour renvoyer un soméclass code>: p> xxx pré>

la mise en œuvre de Assomeclass code> fait simplement retourner ceci code>. Ensuite, vous pourriez faire: p> xxx pré>

et l'appelant de cette méthode serait en mesure d'utiliser l'objet retourné comme étant soit Type: P>

public static <A> SomeClassWrapper<A> makeSomeClass(Class<A> type) {...}


1 commentaires

Merci beaucoup pour cette réponse.