Не удалось открыть реализацию для метода, добавленного в интерфейс из базового класса в Eclipse - PullRequest
3 голосов
/ 28 марта 2019

Я использую Eclipse Neon.

По сути, я создаю новый интерфейс и добавляю к нему существующий метод, найденный в другом базовом классе.

У меня есть класс MyServiceImpl, который расширяет базовый класс GeneralServiceImpl абстрактным методом doB.

Я создал интерфейс GeneralService для 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() { }
}

И мой новый интерфейс включает ожидание использования GeneralServiceImpl метода doB()

public interface MyService {
    public void doC();
    public void doB();
}

Это работает, но в Eclipse, когда я нажимаю на метод doB() (doC() работает) в MyService Open реализаций ( Ctrl + щелчок левой кнопкой мыши), я не могу найти ни одной доступной реализации (см. Ниже) )

Это ошибка Eclipse? Моя установка неправильно построена? мои ожидания неверны?

  • Примечание от GeneralService Я могу открыть реализацию для его doB() метода

  • Обратите внимание, что еще одна причина, по которой мне нужно, это также добавить поддержку Spring Service в существующий метод

Ответы [ 4 ]

3 голосов
/ 06 апреля 2019

Пожалуйста, смотрите это не ошибка.

Давайте разберемся (я сделал изобразительное представление, чтобы лучше понять):

enter image description here

Понятно, что класс GeneralServiceImpl переопределяет функцию doB() реализации интерфейса GeneralService, а также MyServiceImpl реализует функцию doC() интерфейса реализации MyService.

Кроме того, существует отношение наследования между MyServiceImpl и GeneralServiceImpl -> MyServiceImpl extends GeneralServiceImpl, поэтому MyServiceImpl имеет doB(){}.

Теперь мы должны понимать, что IDE, завершение и компилятор используют статическое представление.

Если вы хотите узнать представление во время выполнения, тогда нужно использовать режим отладки.

Итак, если мы увидим, как спроектированы ваши классы и интерфейс, прямой связи между MyService и GeneralServiceImpl нет, поэтому eclipse не знает о своей реализации runtime и, следовательно, не выделяет то же самое. .

Вместо этого пунктирная линия на диаграмме представляет отношение runtime и, следовательно, реализацию функции void doB();.


Добавление дополнительной информации на основе @howlger комментария :

Для Interface реализация class должна переопределить все объявленные функции (кроме abstract). и как IDE Eclipse при поиске реализации функции из Interface, тогда она ищет только непосредственную реализацию в реализующих классах. (как для doC() это работает). [статический вид / компилятор]

Теперь представьте себе, между MyServiceImpl & GeneralServiceImpl у нас есть другой класс SubGeneralServiceImpl, который также overrides doB() как

public class SubGeneralServiceImpl extends GeneralServiceImpl {
    public void doB() {
            //
        }
    }

и теперь MyServiceImpl расширяется SubGeneralServiceImpl и SubGeneralServiceImpl расширяется GeneralServiceImpl.

Итак, даже сейчас MyServiceImpl имеет doB () , но теперь имеет доступ к реализации 2 doB () , которую можно увидеть:

enter image description here

, таким образом, в статическом представлении (компилятор) это абсолютно нормально, поскольку MyServiceImpl переопределяет doB() & doC() ... однако Eclipse как IDE не уверен, какая реализация будет использоваться, что происходит во время выполнения , таким образом, не может дать вам реализацию doB() при попытке получить из MyService Interface.

Надеюсь, это поможет.

2 голосов
/ 01 апреля 2019

GeneralServiceImpl.doB() не является реализацией MyService.doB(), но в MyServiceImpl используется для реализации MyService.doB(). Поэтому было бы неправильно отображать GeneralServiceImpl.doB() как реализацию или определение MyService.doB().

В следующем примере аннотирование FooImpl с помощью @Override приводит к ошибке времени компиляции. В соответствии с спецификацией языка Java 9.6.4.4. это означает, что FooImpl.foo() не реализует или не определяет 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() {}
}

Обратите внимание, что существует больше возможностей для неявной реализации / определения методов, которые не будут показаны в Eclipse: например, инструментарий с помощью агента Java (например, используемый для имитации объектов) или с помощью декларативной структуры.

2 голосов
/ 31 марта 2019

У меня это работает.

Проверено на:

Eclipse IDE для разработчиков Java на предприятиях.

Версия: 2019-03 (4.11.0) Идентификатор сборки: 20190314-1200

Я также протестировал его на новой установке (никаких плагинов, кроме стандартных), и он также работает.

Также протестирован на OSX и Linux (Windows недоступна ... извините)

1 голос
/ 31 марта 2019
  1. Когда вы делаете

ctrl + наведение мыши

, eclipse предоставляет вам 2 варианта:

a.Открытое объявление.

b.Открытая реализация.

Вам нужно выбрать второй вариант.

Я бы предпочел использовать

'ctrl + T'

, чтобы увидеть полную иерархию реализации.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...