Java générique de la méthode de l'héritage et de remplacer les règles
J'ai une classe abstraite qui a une méthode générique et je veux remplacer la méthode générique en substituant des types spécifiques au paramètre générique. Donc, dans le pseudo-code, j'ai ce qui suit:
public abstract class GetAndParse {
public SomeClass var;
public abstract <T extends AnotherClass> void getAndParse(T... args);
}
public class Implementor extends GetAndParse {
// some field declarations
// some method declarations
@Override
public <SpecificClass> void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
Mais pour une raison quelconque, Je ne suis pas autorisé à le faire? Ai-je fait une sorte d'erreur de syntaxe ou est ce genre d'héritage et impérieuses pas permis? Plus précisément, je reçois une erreur à propos de @Override
parce que l'IDE eclipse ne cesse de me rappeler d'implémenter getAndParse
.
Voici comment Je veux que le code ci-dessus fonctionne. Ailleurs dans mon code, il existe une méthode qui attend des instances d'objets qui implémentent GetAndParse
ce qui signifie spécifiquement qu'ils ont une méthode getAndParse
que je peux utiliser. Quand j'appelle getAndParse
sur cette instance, le compilateur vérifie si j'ai utilisé des instances spécifiques de T
de la manière appropriée, donc en particulier T
devrait s'étendre AnotherClass
et il devrait être SpecificClass
.
5 réponses
Ce que nous avons ici, ce sont deux méthodes différentes avec des paramètres de type individuels chacune.
public abstract <T extends AnotherClass> void getAndParse(Args... args);
C'est une méthode avec un paramètre de type nommé T, et délimité par AnotherClass
, ce qui signifie que chaque sous-type de AnotherClass
est autorisé en tant que paramètre de type.
public <SpecificClass> void getAndParse(Args... args)
C'est une méthode avec un paramètre de type nommé SpecificClass
, délimité par Object
(ce qui signifie que chaque type est accueilli comme un paramètre de type). Voulez-vous vraiment cela?
Le paramètre type est-il utilisé à l'intérieur de Args
? Je pense que le problème serait y.
Modifier:
La signification de
public abstract <T extends AnotherClass> void getAndParse(T... args);
Est le appelant de la méthode peut décider avec quel type de paramètre qu'il veut appeler la méthode, tant que c'est une sous-type de AnotherClass
. Cela signifie qu'en effet la méthode peut être appelée avec n'importe quel objet de type AnotherClass
.
Puisque l'appelant peut décider du paramètre type, vous ne pouvez pas dans une sous-classe affiner le type de paramètre à SpecificClass
- ce ne serait pas une implémentation de la méthode, mais une autre méthode avec le même nom (surcharge).
Peut-être que vous voulez quelque chose comme ceci:
public abstract class GetAndParse<T extends AnotherClass> {
public SomeClass var;
public abstract void getAndParse(T... args);
}
public class Implementor extends GetAndParse<SpecificClass> {
// some field declarations
// some method declarations
@Override
public void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
Maintenant, la méthode getAndParse
implémente la méthode de la classe parent.
Vous voyez ce problème à cause du concept appelé "effacement" dans les génériques Java. Java utilise "erasure" pour prendre en charge la rétrocompatibilité. c'est-à-dire le code Java qui n'a pas utilisé de génériques.
Procédure D'Effacement:
Le compilateur effectuera d'abord une vérification de type, puis supprimera(effacera) tous les paramètres de type autant que possible, et insérera également la TypeCasting si nécessaire.
Exemple:
public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);
Deviendra
public abstract void getAndParse(AnotherClass paramAnotherClass);
En classe "Un réalisateur.java",
Le code
public <SpecificClass> void getAndParse(T paramAnotherClass)
Deviendra
public void getAndParse(SpecificClass paramAnotherClass){ }
Le compilateur verra que vous n'avez pas implémenté correctement la méthode abstraite. Il existe une incompatibilité de type entre la méthode abstraite et la méthode implémentée. C'est pourquoi vous voyez l'erreur.
Plus de détails peuvent être trouvés ici. http://today.java.net/pub/a/today/2003/12/02/explorations.html
Non, ce n'est pas valide. Que se passerait-il si quelqu'un avec une référence GetAndParse
l'appelait avec une classe différente s'étendant AnotherClass
?
Cela devient un non-sens quand quelqu'un a une référence à taper GetAndParse et essaie d'appeler la méthode getAndParse. Si le Chat et le chien étendent un Autreclasse. Je devrais m'attendre à pouvoir appeler getandparse#getAndParse avec un chat ou un chien. Mais la mise en œuvre a essayé de le restreindre et de le rendre moins compatible!
Vous ne pouvez pas Remplacer par un type spécifique T car il n'y a en fait (au niveau du bytecode si vous le souhaitez) qu'une seule méthode getAndParse en raison de l'effacement de type (Voir autre réponse):
public abstract void getAndParse(AnotherClass... args); // (1)
Pour chaque type de T, la même méthode est utilisée.
Vous pouvez surcharger (je pense):
public void getAndParse(SpecificClass... args); // (2)
, Mais ce ne sera pas une méthode différente de (1) et il sera pas être appelé par le code générique:
T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass