用超类扩展 javafx.application.Application。为什么 Override 在子类中被忽略?
Extending javafx.application.Application with superclass. Why is Override ignored in subclass?
我需要定义一个 类型 的应用程序,我从中扩展实际应用程序(例如在下面的 TestApp_sub
中)。遗憾的是,这些实际的应用程序覆盖方法不起作用。似乎他们被完全忽略了。下面的包应该打印
A
B
执行中。但只打印
A
相反。
代码
超级class 基于javafx:
package overrideIssue;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class TestApp_super extends Application {
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Pane(), 640, 480);
stage.setScene(scene);
stage.show();
myMethod();
}
public static void main(String[] args) {
launch();
}
public void myMethod(){
System.out.println("A");
}
}
子class(一个实际的应用程序/包含被忽略的覆盖):
package overrideIssue;
public class TestApp_sub extends TestApp_super {
@Override
public void myMethod() {
super.myMethod();
System.out.println("B");
}
}
主要方法:
package overrideIssue;
public class App {
public static void main( String[] args ) {
TestApp_sub.main( args );
}
}
建议
根据 javatpoint 应满足以下条件:
Java 方法覆盖的规则
- 该方法必须与父方法同名 class
- 该方法必须具有与父方法相同的参数 class。
- 必须存在 IS-A 关系(继承)。
(但是它是一个 javafx.application.Application
,它没有被实例化为一个对象。)
我在 Whosebug 上发现了几个看似相似的问题,但是我看不到这个问题的解决方案。非常感谢。
这里的问题是 Application.launch
的工作方式。遍历调用堆栈以确定调用 Application.launch
的 class 并构建此 class 的实例以用于启动应用程序。您没有改变 main
方法调用 Application.launch
是 TestApp_super
class.
的一部分这一事实
不是编译器在编译时确定 class 包含 TestApp_sub.main( args );
的 main
方法,因此字节代码中没有留下关于您正在使用 TestApp_sub
.
您可以将应用程序 class 传递给 launch
的重载版本:
Application.launch(TestApp_sub.class, args);
来自 Application#launch(String...)
的文档:
Launch a standalone application. This method is typically called from the main
method. It must not be called more than once or an exception will be thrown. This is equivalent to launch(TheClass.class, args)
where TheClass
is the immediately enclosing class of the method that called launch
[emphasis added].
在你的例子中,调用 launch
的方法的 "immediately enclosing class" 是 TestApp_super
。这意味着实例化并用作应用程序 class 的 TestApp_super
,而不是 TestApp_sub
。换句话说,您没有将 class 与覆盖的方法一起使用,您看到的输出是预期的。
要使用您想要的class,至少有三个选项:
使用Application#launch(Class,String...)
:
package overrideIssue;
import javafx.application.Application;
public class App {
public static void main( String[] args ) {
Application.launch(TestApp_sub.class, args);
}
}
现在您明确告诉 JavaFX 哪个 class 用作应用程序 class。您甚至可以添加逻辑来检查命令行参数并决定将哪个 class 传递给 launch
.
只需将您想要的应用程序作为主要应用程序即可class。换句话说,在命令行上指定适当的class。
在 TestApp_sub
class 中添加一个 public static void main(String[])
方法。
package overrideIssue;
public class TestApp_sub extends TestApp_super {
public static void main(String[] args) {
launch(args);
}
@Override
public void myMethod() {
super.myMethod();
System.out.println("B");
}
}
这不会覆盖TestApp_super
class中的main
方法,它只会隐藏 it——静态方法不能被覆盖。调用哪个静态方法由调用该方法的声明类型决定;注意我说的是声明类型,而不是运行时类型,因为要调用的静态方法是在编译时决定的。由于您使用 TestApp_sub.main(args)
中的方法 TestApp_sub
被调用(假设您已经像上面那样添加了它)。但是,如果您要使用 TestApp_super.main(args)
,它将调用 TestApp_super
中的方法,而不管子 class.
中是否存在具有相同签名的方法
现在 TestApp_sub
是调用 launch
的方法的 "immediately enclosing class",它会被实例化和使用 TestApp_sub
。
我需要定义一个 类型 的应用程序,我从中扩展实际应用程序(例如在下面的 TestApp_sub
中)。遗憾的是,这些实际的应用程序覆盖方法不起作用。似乎他们被完全忽略了。下面的包应该打印
A
B
执行中。但只打印
A
相反。
代码
超级class 基于javafx:
package overrideIssue;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class TestApp_super extends Application {
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Pane(), 640, 480);
stage.setScene(scene);
stage.show();
myMethod();
}
public static void main(String[] args) {
launch();
}
public void myMethod(){
System.out.println("A");
}
}
子class(一个实际的应用程序/包含被忽略的覆盖):
package overrideIssue;
public class TestApp_sub extends TestApp_super {
@Override
public void myMethod() {
super.myMethod();
System.out.println("B");
}
}
主要方法:
package overrideIssue;
public class App {
public static void main( String[] args ) {
TestApp_sub.main( args );
}
}
建议
根据 javatpoint 应满足以下条件: Java 方法覆盖的规则
- 该方法必须与父方法同名 class
- 该方法必须具有与父方法相同的参数 class。
- 必须存在 IS-A 关系(继承)。
(但是它是一个 javafx.application.Application
,它没有被实例化为一个对象。)
我在 Whosebug 上发现了几个看似相似的问题,但是我看不到这个问题的解决方案。非常感谢。
这里的问题是 Application.launch
的工作方式。遍历调用堆栈以确定调用 Application.launch
的 class 并构建此 class 的实例以用于启动应用程序。您没有改变 main
方法调用 Application.launch
是 TestApp_super
class.
不是编译器在编译时确定 class 包含 TestApp_sub.main( args );
的 main
方法,因此字节代码中没有留下关于您正在使用 TestApp_sub
.
您可以将应用程序 class 传递给 launch
的重载版本:
Application.launch(TestApp_sub.class, args);
来自 Application#launch(String...)
的文档:
Launch a standalone application. This method is typically called from the
main
method. It must not be called more than once or an exception will be thrown. This is equivalent tolaunch(TheClass.class, args)
whereTheClass
is the immediately enclosing class of the method that calledlaunch
[emphasis added].
在你的例子中,调用 launch
的方法的 "immediately enclosing class" 是 TestApp_super
。这意味着实例化并用作应用程序 class 的 TestApp_super
,而不是 TestApp_sub
。换句话说,您没有将 class 与覆盖的方法一起使用,您看到的输出是预期的。
要使用您想要的class,至少有三个选项:
使用
Application#launch(Class,String...)
:package overrideIssue; import javafx.application.Application; public class App { public static void main( String[] args ) { Application.launch(TestApp_sub.class, args); } }
现在您明确告诉 JavaFX 哪个 class 用作应用程序 class。您甚至可以添加逻辑来检查命令行参数并决定将哪个 class 传递给
launch
.只需将您想要的应用程序作为主要应用程序即可class。换句话说,在命令行上指定适当的class。
在
TestApp_sub
class 中添加一个public static void main(String[])
方法。package overrideIssue; public class TestApp_sub extends TestApp_super { public static void main(String[] args) { launch(args); } @Override public void myMethod() { super.myMethod(); System.out.println("B"); } }
这不会覆盖
中是否存在具有相同签名的方法TestApp_super
class中的main
方法,它只会隐藏 it——静态方法不能被覆盖。调用哪个静态方法由调用该方法的声明类型决定;注意我说的是声明类型,而不是运行时类型,因为要调用的静态方法是在编译时决定的。由于您使用TestApp_sub.main(args)
中的方法TestApp_sub
被调用(假设您已经像上面那样添加了它)。但是,如果您要使用TestApp_super.main(args)
,它将调用TestApp_super
中的方法,而不管子 class.现在
TestApp_sub
是调用launch
的方法的 "immediately enclosing class",它会被实例化和使用TestApp_sub
。