J'utilise Eclipse Neon.
En gros, je crée une nouvelle interface et j'y ajoute une méthode existante trouvée dans une classe de base différente.
J'ai une classe MyServiceImpl qui étend la classe de base
GeneralServiceImpl
avec la méthode abstraite doB
.
J'ai créé une interface GeneralService
pour GeneralServiceImpl
et a également ajouté la méthode doB
:
public interface MyService { public void doC(); public void doB(); }
Et ma nouvelle interface prévoit d'utiliser la méthode GeneralServiceImpl
doB()
public interface GeneralService { abstract void doB(); } public class GeneralServiceImpl implements GeneralService { @Override public void doB() { } } } @Service public class MyServiceImpl extends GeneralServiceImpl implements MyService { @Override public void doC() { } }
Cela fonctionne mais en éclipse lorsque je clique sur la méthode doB ()
( doC ()
fonctionne) dans MyService Open Implementation ( Ctrl + Clic gauche de la souris) Je ne trouve aucune implémentation disponible (voir ci-dessous)
S'agit-il d'un bogue Eclipse? Mon décor est-il mal construit? mes attentes sont-elles fausses?
Note de GeneralService
Je peux ouvrir l'implémentation pour sa méthode doB ()
Notez qu'une autre raison pour laquelle j'en ai besoin est également d'ajouter un support Spring Service à une méthode existante
4 Réponses :
Cela fonctionne pour moi.
Testé le:
Eclipse IDE pour les développeurs Enterprise Java.
Version: 2019-03 (4.11.0) ID de build: 20190314-1200
Je l'ai également testé sur une nouvelle installation (aucun plug-in autre que celui par défaut) et cela fonctionne également.
Également testé sur OSX et Linux (pas de Windows disponible ... désolé)
J'utilise Eclipse Neon
Testé de la même manière dans: Eclipse Java EE IDE pour les développeurs Web. Version: Neon.3 Release (4.6.3) ID de build: 20170314-1500
Cela fonctionne à la fois sur Linux et Mac. Même code que précédemment, même résultat positif.
@ user7294900 Eclipse Neon (4.6) est obsolète et n'a pas été maintenu depuis des années. Veuillez mettre à niveau vers Eclipse 2019-03 (4.11).
@howlger J'ai mis à jour ma réponse avec un exemple vérifié
Avec la dernière mise à jour, je peux reproduire le même comportement sur les deux versions d'Eclipse. Et si je peux me permettre, ce n'est pas la faute d'Eclipse mais une faute de conception. Je comprends que vous avez un peu repoussé les limites pour voir ce qui se passe, mais s'il s'agit d'un design du monde réel, je suggère de le revoir. La méthode doB () est correctement implémentée dans GeneralServiceImpl, en fait Eclipse la trouve comme une implémentation de GeneralService.doB (). Puisque nous en sommes à la conception: toutes les méthodes d'une interface sont par définition publiques et abstraites, donc l'ajout de ces mots-clés est une odeur de code. Conclusion: pour moi ce n'est pas un bug avec Eclipse.
@ user7294900 Je vois ce que tu veux dire. Dans GeneralServiceImpl
, la méthode doB ()
n'est pas une implémentation de MyService
même si elle est utilisée comme implémentation dans MyServiceImpl code > pour
MyService
. IMHO montrant GeneralServiceImpl # doB ()
comme implémentation de MyService # doB ()
serait faux, mais il serait bien d'avoir un indice que GeneralServiceImpl # doB ()
est utilisé dans MyServiceImpl
comme implémentation de MyService # doB ()
.
@howlger vous avez raison, en fait j'ai repensé les classes, mais la question demeure
ctrl + survol de la souris
, eclipse vous offre 2 options:
a. Déclaration ouverte.
b. Implémentation ouverte.
Vous devez sélectionner la deuxième option.
'ctrl + T'
pour voir la hiérarchie complète de mise en œuvre.
J'espère que cela aide.
Je choisis la deuxième option, mais je ne trouve pas d'implémentations
Ne vous a-t-il pas montré MyServiceImpl dans la liste déroulante? c'est vraiment étrange car j'utilise ces raccourcis depuis que j'ai commencé la programmation java. Pouvez-vous vous assurer que vous êtes dans la perspective java?
Avec l'exemple mis à jour, il devient évident que 'void doB ()' provient de GeneralService et MyService. Je doute que cela vous donne des résultats fiables. Comment MyserviceImpl doit-il décider que doB () provient de MyService ou GeneralService? En réalité, doB () dans MyserviceImpl est de GeneralServiceImpl donc, eclipse n'est pas confondue; c'est l'inverse :-)
Je voulais utiliser la méthode existante (non spring) dans une nouvelle interface (spring) sans l'appeler explicitement, je redessine les classes, mais la question demeure car cela fonctionne, c'est-à-dire que l'implémentation se trouve en temps réel mais pas dans eclipse
cela fonctionne parce que jvm applique l'intelligence trouve l'implémentation correcte au moment de l'exécution (pas au moment de la compilation).
GeneralServiceImpl.doB () n'est pas une implémentation de MyService.doB()
mais utilisé dans MyServiceImpl
pour implémenter MyService.doB ()
. Par conséquent, il serait faux d'afficher GeneralServiceImpl.doB ()
comme implémentation ou définition de MyService.doB ()
.
Dans l'exemple suivant, annoter FooImpl
avec @Override
conduit à une erreur de compilation. Selon la Spécification du langage Java 9.6.4.4. cela signifie que FooImpl.foo ()
n'implémente ni ne définit API.foo()
:
class MyClass extends FooImpl implements API { @Override // <- correct public void bar() {}; } interface API { void foo(); void bar(); } class FooImpl { // @Override <- compile error public void foo() {} }
S'il vous plaît voir ce n'est pas un bug.
Permet de comprendre (j'ai fait une représentation picturale pour mieux comprendre):
Il est clair que la classe GeneralServiceImpl
remplace la fonction doB ()
d'implémentation de l'interface GeneralService
ainsi que MyServiceImpl
implémente la fonction doC ()
de son interface d'implémentation MyService
.
De plus, il existe une relation d'héritage entre MyServiceImpl
et GeneralServiceImpl
-> MyServiceImpl
étend GeneralServiceImpl
, donc MyServiceImpl
a doB ( ) {}
.
Nous devons maintenant comprendre ici que les IDE, la complétion et le compilateur utilisent la vue statique.
Si vous voulez connaître la vue d’exécution, alors on doit nous Le mode de débogage.
Donc, si nous voyons la façon dont vos classes et votre interface sont conçues, il n'y a pas de relation directe entre MyService
et GeneralServiceImpl code >, donc
eclipse
n'est pas au courant de son implémentation runtime
et ne met donc pas en évidence la même chose.
Au contraire, cette ligne pointillée dans le diagramme représente relation d'exécution
et donc implémentation de la fonction void doB ();
.
Ajout d'informations sur la base de @howlger comment :
Pour une Interface
implémentant la classe
, il faut remplacer toutes les fonctions déclarées (à moins que abstract
). et en tant qu'EDI Eclipse
lors de la recherche d'une implémentation d'une fonction depuis Interface
, il ne recherche que l'implémentation directe dans les classes d'implémentation. (comme pour doC ()
cela fonctionne). [vue statique / compilateur]
Maintenant, imaginez entre MyServiceImpl
et GeneralServiceImpl
nous avons une autre classe SubGeneralServiceImpl
qui aussi remplace doB ()
comme
public class SubGeneralServiceImpl extends GeneralServiceImpl { public void doB() { // } }
et maintenant MyServiceImpl
étend SubGeneralServiceImpl
et SubGeneralServiceImpl étend encore
GeneralServiceImpl
.
Donc, même maintenant, MyServiceImpl
a doB () mais maintenant l'accès à l'implémentation 2 doB () , qui peut être vu:
donc en vue statique (compilateur) c'est tout à fait correct dans la mesure où MyServiceImpl remplace doB ()
& doC ()
... cependant Eclipse en tant qu'EDI ne sait pas quelle implémentation va être utilisée runtime, donc pas en mesure de vous donner l'implémentation de doB () lors de la tentative d'obtention de l'interface MyService
.
J'espère que cela vous aidera.
Ce n'est pas absolument exact. Le fait qu'une classe implémente une interface ou non est déterminé au moment de la compilation et non au moment de l'exécution. Par exemple, public class C {public int compareTo (Object o) {return 0; } public static void main (String [] args) {System.out.println (nouvelle instance C () de Comparable); }}
renvoie false
, mais avec C implémente Comparable
true
.
Le problème est que GeneralServiceImpl.doB ()
n'est qu'une implémentation de MyService.doB ()
dans MyServiceImpl
, affichant ainsi GeneralServiceImpl. doB ()
comme implémentation de MyService.doB ()
serait faux. Il n'y a pas de MyServiceImpl.doB ()
dans le code qui peut être affiché comme implémentation. Il n'existe que par MyServiceImpl étend GeneralServiceImpl implémente MyService
. Il n'y a rien qui puisse être affiché même s'il est connu par l'analyse de code statique.
Bonjour, je n'ai pas compris votre point du premier commentaire et je ne pourrais pas être plus d'accord sur votre deuxième commentaire car GeneralServiceImpl.doB ()
est la seule implémentation de MyService.doB () code>, d'après ce que je vois de la question, c'est un beau cas de
polymorphisme dynamique
.
Cela peut sembler vrai, mais ce n'est pas du polymorphisme dynamique. Si vous renommez GeneralServiceImpl.doB ()
, vous obtiendrez une erreur de compilation car dans MyServiceImpl
doB ()
est manquant pour implémenter MyService
. Le fait que MyServiceImpl
étend GeneralServiceImpl
est corrigé dans le bytecode. La résolution des liaisons est effectuée ici au moment de la compilation, pas au moment de l'exécution.
Salut @howlger, j'ai édité la réponse avec un scénario..Je dirais merci à vos commentaires qui ont rendu la réponse plus détaillée! J'espère que nous sommes synchronisés maintenant!
Je suis désolé, mais je crois toujours que la liaison se fait ici de manière statique et non dynamique.
Sur quel mot dans quelle ligne du code vous avez posté, cliquez-vous avec la souris?
@Abra
doD ()
dansMyService
. Mis à jour ma questionFonctionne pour moi avec Eclipse Oxygen sur Windows 7 avec Java 8.
@Abra J'utilise Eclipse Neon