#java #eclipse #interface #abstract-class
#java #eclipse #интерфейс #абстрактный класс
Вопрос:
Я использую 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 Implementation (Ctrl щелчок левой кнопкой мыши), я не могу найти какую-либо доступную реализацию (см. Ниже)
Это ошибка Eclipse? Неправильно ли сконструирован мой параметр? мои ожидания неверны?
-
Примечание от
GeneralService
я могу открыть реализацию для своегоdoB()
метода -
Обратите внимание, что еще одна причина, по которой мне это нужно, также заключается в добавлении поддержки Spring Service к существующему методу
Комментарии:
1. На какое слово, в какой строке опубликованного вами кода вы нажимаете мышью?
2. @Abra
doD()
вMyService
. Обновил мой вопрос3. У меня работает с Eclipse Oxygen в Windows 7 с Java 8.
4. @Abra Я использую Eclipse Neon
Ответ №1:
Пожалуйста, смотрите, это не ошибка.
Давайте разберемся (я сделал графическое представление, чтобы лучше понять):
Ясно, что 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
amp; GeneralServiceImpl
у нас есть другой класс, SubGeneralServiceImpl
который также overrides doB()
как
public class SubGeneralServiceImpl extends GeneralServiceImpl {
public void doB() {
//
}
}
и теперь MyServiceImpl
расширяется SubGeneralServiceImpl
и SubGeneralServiceImpl
еще больше расширяется GeneralServiceImpl
.
Итак, даже сейчас MyServiceImpl
есть doB(), но теперь доступен доступ к двум реализациям doB (), которые можно увидеть :
таким образом, в статическом представлении (компилятор) это абсолютно нормально в том, что касается MyServiceImpl
переопределений doB()
amp; doC()
… однако Eclipse как IDE не уверен, какая реализация будет использоваться, которая поставляется во время выполнения, поэтому не может предоставить вам реализацию doB()
при попытке получения из MyService
интерфейса.
Надеюсь, это поможет.
Комментарии:
1.Это не совсем точно. Реализует ли класс интерфейс или нет, определяется во время компиляции, а не во время выполнения. Например,
public class C { public int compareTo(Object o) { return 0; } public static void main(String[] args) { System.out.println(new C() instanceof Comparable); } }
возвращаетfalse
, но сC implements Comparable
true
.2. Проблема в том, что
GeneralServiceImpl.doB()
это всего лишь реализацияMyService.doB()
вMyServiceImpl
, поэтому отображениеGeneralServiceImpl.doB()
как реализацииMyService.doB()
было бы неправильным. В коде нетMyServiceImpl.doB()
того, что может быть показано как реализация. Он существует только с помощьюMyServiceImpl extends GeneralServiceImpl implements MyService
. Нет ничего, что можно было бы отобразить, даже если это известно из статического анализа кода.3. Привет, не понял вашу точку зрения из 1-го комментария, и я не могу не согласиться с вашим 2-м комментарием, поскольку
GeneralServiceImpl.doB()
это единственная реализацияMyService.doB()
, насколько я вижу из вопроса, это прекрасный примерdynamic polymorphism
.4.Может показаться, что это так, но это не динамический полиморфизм. Если вы переименуете
GeneralServiceImpl.doB()
, вы получите ошибку компиляции, потому что вMyServiceImpl
doB()
отсутствует для реализацииMyService
. ЭтоMyServiceImpl
расширениеGeneralServiceImpl
исправлено в байт-коде. Разрешение привязок выполняется здесь во время компиляции, а не во время выполнения.5. Привет @howlger, я отредактировал ответ с помощью sceanrio .. Я бы сказал спасибо вашим комментариям, которые сделали ответ более подробным! Надеюсь, теперь мы синхронизированы!
Ответ №2:
У меня это работает.
Протестировано на:
Eclipse IDE для корпоративных разработчиков Java.
Версия: 2019-03 (4.11.0) Идентификатор сборки: 20190314-1200
Я также протестировал его при новой установке (никаких плагинов, отличных от стандартных), и он также работает.
Также протестировано на OSX и Linux (Windows недоступна … извините)
Комментарии:
1. Я использую Eclipse Neon
2. Протестировано то же самое в: Eclipse Java EE IDE для веб-разработчиков. Версия: Neon.3 Release (4.6.3) Идентификатор сборки: 20170314-1500
3. Это работает как на Linux, так и на Mac. Тот же код, что и раньше, тот же положительный результат.
4. @user7294900 Eclipse Neon (4.6) устарел и не поддерживался годами. Пожалуйста, обновитесь до Eclipse 2019-03 (4.11).
5. @howlger Я обновил свой ответ проверенным примером
Ответ №3:
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-агент (например, используемый для макетирования объектов) или через декларативную платформу.
Ответ №4:
- Когда вы делаете
ctrl наведение курсора мыши
eclipse предоставляет вам 2 варианта:
a. Открытое объявление.
b. Откройте реализацию.
Вам нужно выбрать второй вариант.
- Я бы предпочел использовать
‘ctrl T’
чтобы увидеть полную иерархию реализации.
Надеюсь, это поможет.
Комментарии:
1. Я выбираю второй вариант, но тогда он не находит реализаций
2. Разве это не показывало вам MyServiceImpl в раскрывающемся списке? это действительно странно, поскольку я использую эти ярлыки с тех пор, как начал программировать на Java. Можете ли вы убедиться, что вы находитесь в перспективе Java?
3. В обновленном примере становится очевидно, что ‘void doB()’ поступает из GeneralService и MyService. Я сомневаюсь, что это даст вам надежные результаты. Как ожидается, MyServiceImpl решит, что doB () поступает из MyService или GeneralService? На самом деле, doB() в MyServiceImpl взят из GeneralServiceImpl, так что eclipse не перепутан; все наоборот 🙂
4. Я хотел использовать существующий (не spring) метод в новом интерфейсе (spring) без его явного вызова, я перепроектирую классы, но все еще остается вопрос, потому что это работает, т. Е. реализация найдена в реальном времени, но не в eclipse
5. это работает, потому что jvm применяет интеллект, который находит правильную реализацию во время выполнения (не во время компиляции).