Java Génériques conflit de nom, la méthode n'est pas correctement remplacée
J'ai vu des différentes questions à ce sujet, mais je trouve ce sujet pour être très déroutant.
Tout ce que je veux, c'est avoir une classe abstraite qui implémente une interface, et ont une classe étendant cette classe abstraite, de sorte que l'unité de la classe doit implémenter getKommune()
et setKommune(Kommune kommune)
, mais pas dans l'autre méthode, parce que c'est dans la classe abstraite.
J'ai l'interface suivante.
public interface KommuneFilter {
<E extends AbstractKommune<?>> void addKommuneFromCurrentUser(E e);
Kommune getKommune();
void setKommune(Kommune kommune);
}
Et cette classe Abstraite
public abstract class AbstractKommune<E extends AbstractKommune<?>> implements KommuneFilter {
@PrePersist
void addKommuneFromCurrentUser(E e) {
Kommune k = e.getKommune();
}
}
Et je veux l'utiliser comme ceci
public class Person extends AbstractKommune<Person> {
private Kommune kommune;
public void setKommune(Kommune kommune) {this.kommune=kommune;}
public Kommune getKommune() {return kommune;}
}
Cependant, je reçois
conflit de Nom: La méthode de a le même effacement de type, mais ne remplace pas, il
Pourquoi n'est-il pas correctement remplacée?
Mise à JOUR
Grâce à @Bozho, la solution est: est-ce
public interface KommuneFilter<E extends AbstractKommune<?>> {
public void addKommuneFromCurrentUser(E e);
}
public abstract class AbstractKommune<E extends AbstractKommune<?>> implements KommuneFilter<E>
public class Person extends AbstractKommune<Person>
OriginalL'auteur Shervin Asgari | 2010-03-30
Vous devez vous connecter pour publier un commentaire.
Je suggère de faire l'interface générique, plutôt que de sa méthode:
Et puis
parce que dans votre conception originale, la méthode spécifiée par l'interface est une méthode générique, et votre classe abstraite de la tentative de
@Override
il n'en est pas une.OriginalL'auteur Bozho
La raison pour laquelle c'est un conflit de nom et pas un remplacement est parce qu'il ne l'est pas. La méthode spécifiée par l'interface est une méthode générique; votre classe abstraite de tenter de les remplacer, il ne l'est pas.
Plus concis code qui reproduit votre problème est le suivant:
Le problème ici est que
interface I
spécifie que les réalisateurs doivent fournir une méthode générique<E>foo
(il peut être un<Integer>foo
,<Boolean>foo
, etc), mais dire, unC<String>
n'a en fait qu'foo(String)
.Un moyen de résoudre ce problème est de faire
C.foo
une méthode générique, pour bien@Override
la méthode générique deinterface I
:Vous pouvez voir ce que cela fait, dans le code ci-dessus: vous avez un type générique
C<E>
avec une méthode générique<T>foo
(vous pouvez utiliserE
au lieu deT
, mais ça n'aurait pas changer quoi que ce soit-c'est encore une méthode générique avec son propre type de paramètre).Maintenant un
C<String>
a également<Integer>foo
, etc, comme spécifié parinterface I
.Si ce n'est pas quelque chose que vous avez besoin, alors vous voudrez probablement faire
interface I<E>
générique à la place:Maintenant le type et la méthode de partage le même type de paramètre (par exemple, un
I<Boolean>
ne dispose que d'unfoo(Boolean)
, unC<String>
ne dispose que d'unfoo(String)
) qui est probablement ce que vous aviez prévu à l'origine.@Override
annotation. Ce que vous êtes lui disant de faire est de cacher le paramètre générique de la classe par l'introduction d'un autre avec le même nom sur la méthode. (Eclipse donne "Le paramètre de type E est de cacher la type E")Historiquement, j'ai toujours écrire
@Override
au lieu de "remplacer" pour me rappeler (et autres) à toujours utiliser l'annotation. Je me rends compte que cela provoque une confusion ici. Il devrait être plus clair maintenant. Vous avez raison sur le masquage de la partie; je ne pense pas que c'est une grosse affaire personnellement.à l'aide de
T
au lieu deE
pour la méthode serait mieux, mais l'ensemble de la "conception" se sent toujours mal.Nom de la clandestinité est bien dans la bonne contextes, par exemple
this.kommune = kommune;
dans le code ci-dessus. La raison pourquoi je préfère le nom de cacher ici, au lieu d'introduire un nouveau paramètre de typeT
est parce que les deux ont la même limite. Si ce n'est pas le cas, alors bien entendu un nouveau nom qui ne cache pas un nom pour un autre type serait le mieux.Bon, j'ai pris tout le monde de la suggestion et est allé à discuter du problème en termes plus généraux, et abordé les différences entre les deux solutions possibles.
OriginalL'auteur polygenelubricants