Почему мой унаследованный класс приложения Java FX (App1 расширяет приложение -> App2 расширяет App1) игнорирует перезаписанные функции при запуске?

У меня проблема с Java FX и реализацией очень странного приложения. Позвольте мне показать это с помощью кода:

Представьте себе базовое приложение:

import javafx.application.Application;
import javafx.stage.Stage;

public class JavaFXApp extends Application {
    // constructor, ...

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        // important stuff
        initialize();
        // important stuff
        stage.show();
    }

    public void initialize() {
        System.out.println("default");
        // basically abstract
    }

    // and other functions.
}

и его расширение (как и предполагалось):

public class JavaFXAppExtended extends JavaFXApp {
    // constructor, ...

    @Override
    public void initialize() {
        System.out.println("extended");
    }
}

Теперь вызов JavaFXApp не вызывает у меня никаких проблем. Но при вызове JavaFXAppExtended@Overwrite по сути игнорируется и вызывается initialize из родительского класса. Тем самым:

JavaFXApp.main(args);
-> default
JavaFXAppExtended.main(args);
-> default

при этом ожидалось «расширенное».

Почему initialize от родителя JavaFXAppExtended вызывается вместо @Overwrite? Я пропустил что-то важное? Это незаконно? Я недостаточно опытен? Может это просто ошибка? Я не знаю. Но я хочу знать.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
84
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

На самом деле JavaFXAppExtended.main(args) вызывает статический JavaFXApp.main, поскольку в JavaFXAppExtended нет main. В коде вызова JavaFXAppExtended не остается никаких следов. Точно такой же код, как JavaFXApp.main(args).

В статических функциях нет наследования this. Отсюда и название JavaFXApp.launch.

Спасибо. Я пропустил добавление отдельного основного компонента в JavaFX Api Extended.

elai 07.05.2024 20:34

Ответ Йопа Эггена правильный, но я просто хочу добавить еще немного информации.

Метод launch(String..) представляет собой удобную перегрузку launch(Class,String...), когда класс приложения JavaFX и основной класс являются одним и тем же. Аргумент класса неявно является вызывающим классом. А класс вызывающего объекта — это класс, в котором объявлен вызывающий метод. В вашем вопросе классом вызывающего абонента является JavaFXApp, потому что именно там объявлен main и из него main вы звоните launch.

Платформа JavaFX берет класс приложения и создает его экземпляр. Затем он вызывает методы init, start и stop в соответствии с документированным жизненным циклом приложения JavaFX. Таким образом, в вашем вопросе объект, у которого вызван метод start, является экземпляром JavaFXApp, а не JavaFXAppExtended. Другими словами, переопределение initialize не игнорируется, скорее вы вызываете initialize для объекта, отличного от того, который вы ожидали.

Если вы хотите, чтобы JavaFXAppExtended был классом приложения, у вас есть два варианта:

  1. Используйте launch(Class,String...), чтобы явно передать JavaFXAppExtended.class.

  2. Вызовите launch(String..) из метода, объявленного в классе JavaFXAppExtended (это решение , которое вы выбрали ).

Обратите внимание: немного странно иметь две конкретные реализации Application в одном проекте. Возможно, JavaFXApp должен быть абстрактным и не содержать метода main. Или, если какой класс используется в качестве класса приложения, определяется каким-то условием времени выполнения, то, возможно, было бы лучше перенести этот выбор в другой основной класс. Например:

import javafx.application.Application;

public class Main {

  // With this approach, neither application class should have a main method.
  public static void main(String[] args) {
    if (/* some condition */) {
      Application.launch(JavaFXAppExtended.class, args);
    } else {
      Application.launch(JavaFXApp.class, args);
    }
  }
}

Действительно ценная справочная информация. И что немного странно иметь два приложения как таковых. Можно мыслить абстрактный базовый класс приложения.

Joop Eggen 07.05.2024 23:25

Другие вопросы по теме