3
votes

Impossible d'ouvrir l'implémentation pour la méthode ajoutée à l'interface à partir de la classe de base dans Eclipse

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 commentaires

Sur quel mot dans quelle ligne du code vous avez posté, cliquez-vous avec la souris?


@Abra doD () dans MyService . Mis à jour ma question


Fonctionne pour moi avec Eclipse Oxygen sur Windows 7 avec Java 8.


@Abra J'utilise Eclipse Neon


4 Réponses :


2
votes

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é)


8 commentaires

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 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



1
votes
  1. Quand vous le faites

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.

  1. Je préférerais utiliser

'ctrl + T'

pour voir la hiérarchie complète de mise en œuvre.

J'espère que cela aide.


5 commentaires

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).



2
votes

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() {}
}


0 commentaires

3
votes

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):

 entrez la description de l'image ici

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:

 entrez la description de l'image ici

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.


6 commentaires

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 () , 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.