- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
问题:我说的对吗 super()
在继承类的字段初始化完成之前调用构造函数,这样初始化就可以覆盖我已经初始化的内容?
标题和问题可能听起来有些令人困惑,所以我会尽力澄清我的问题。
我有一个abstract class Geometry
其中有 protected abstract void
方法。该方法在 Geometry 的构造函数中调用。我发现这个电话导致了我遇到的问题。
在我的扩展类(class)中,ExtendedGeometry
我通过调用私有(private)方法来实现抽象方法:
@Override
protected void createGeometry() {
loadModel();
}
private void loadModel()
方法填充 vertexList
就完成了。
vertexList
定义为private ArrayList<Integer> vertexList = new ArrayList<Integer>();
.
当我现在调用update()
时在我的模型上,vertexList 似乎是空的。甚至在此之前,虽然我如上所示直接初始化了变量,但它似乎是 null
在 loadModel()
方法。
所以我认为我的步骤是:
ExtendedGeometry
的(隐式)构造函数.loadModel()
.因此,在第 4 步中,我预计变量不为空,并在第 7 步中被填充。
为了解决这个问题,我找到了三个解决方案:
loadModel()
在我的 ExtendedGeometry
的构造函数中而不是从覆盖的 createGeometry()
调用它。 init()
Geometry
的方法类,然后调用 createGeometry()
.因此,在尝试了所有这些内容之后,我意识到解释似乎是我的父类(super class)能够使用声明,但不能使用我的子类的初始化。这使我得出结论,已完成的步骤是:
ExtendedGeometry
的(隐式)构造函数.super()
调用构造函数。ExtendedGeometry
的成员得到初始化。 (什么会覆盖使用 super()
完成的初始化。)所以我的问题是一个简单的是/否问题(如果我错了,可以通过解释来扩展 - 或者如果我是对的,可以添加):
我说得对吗 super()
在我的继承类的字段初始化完成之前调用构造函数,这样初始化就可以覆盖我已经初始化的内容?
我首先认为这是一个可见性问题,但在追踪问题时,这似乎是我能想到的唯一解决方案。
只是为了完整性,也许为了更好地理解这里是我减少了 95% 的代码,抱歉它没有 JavaDoc。但我添加了一些评论来显示问题并进行解释。
最重要的一个,这里是ExtendedGeometry.java
: 封装几何形状;
import java.util.ArrayList;
public class ExtendedGeometry extends Geometry {
// PROBLEM 1: the ArrayList is already initialized here
private ArrayList<Integer> vertexList = new ArrayList<Integer>();
// usually this is Vector3f from lwjgl, but for
// STO I changed it to Integer
private void loadModel() {
// PROBLEM 2: but the ArrayList is null here!
System.out.println("Initializing vertexList which is " + vertexList);
// PROBLEM 3: leaving the following lines out
// does not change anything in the output
// of the update() method
if(vertexList == null)
vertexList = new ArrayList<Integer>();
// PROBLEM 4: filling the "newly" initialized vertexList,
// but not the old one
vertexList.add(1);
vertexList.add(2);
vertexList.add(3);
}
public void update() {
// PROBLEM 5: as you can see, you see nothing:
// the vertexList has no content
System.out.println("vertexList of size: " + vertexList.size());
for(Integer i : vertexList) {
System.out.print(i);
}
System.out.println();
}
/*// PROBLEM 6 / SOLUTION: If I leave out the loadModel in
// createGeometry() but use this constructor instead
// it works
public SpecializedGeometry() {
loadModel();
}
*/
@Override
protected void createGeometry() {
loadModel();
}
}
Geometry.java
类,它的父类(super class):
package geometry;
public abstract class Geometry {
public Geometry() {
// every geometry has to be created
createGeometry();
}
/*// If I add an init method like this, it works
public void init() {
createGeometry();
// of course this line has to be removed
// from the constructor
}
*/
// this is the abstract method to create a geometry
protected abstract void createGeometry();
}
Simulation.java
只是演示了我的程序的一般构建方式:
package simulation;
import geometry.ExtendedGeometry;
public class Simulation {
private ExtendedGeometry geometry = null;
public Simulation() {
}
public boolean init() {
// initializes all simulation stuff,
// now only creates the geometry
geometry = new ExtendedGeometry();
// geometry.init(); // this is a possible fix, see Geometry.java
return true;
}
public void update() {
// does calculations and updates everything
// accordingly
if(geometry != null) {
geometry.update();
}
}
}
MainWindow.java
,这里没什么特别的:
package main;
import simulation.Simulation;
public class MainWindow {
private Simulation simulation = null;
public boolean init() {
// create the simulation and initialize it
// usually here is a bunch of initializations
simulation = new Simulation();
return simulation.init();
}
public void run() {
// in this example I close after 10 loop runs,
// of course 1 would be sufficient as well
int x = 0;
// the main loop handles inputs, event manager,
// updates, drawing, ...
while(x++ < 10) {
// update simulation
simulation.update();
}
}
}
最后是无聊的Main.java
:
package main;
public class Main {
public static void main(String[] args) {
MainWindow mw = new MainWindow();
if(mw.init()) { // init and
mw.run(); // run main loop
}
}
}
最佳答案
我相信您已经回答了您自己的问题:是的,扩展类在子类初始化之前已完全初始化。
您已经遇到了 OOD 的基本规则,您应该“永远”从构造函数中调用非静态、非 final方法。如果构造函数调用可以被子类重写的方法,这种类型的错误太常见了。
关于java - 继承类和父类(super class)的初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20189065/
问题比较Java,但是我想在Android中实现: 假设有 3 个或更多类相互扩展: class A { ... int color; ... } class B extend
我知道标题听起来有点奇怪,但这正是我愿意做的。简单解释:A类是B类的子类,B类也是C类的子类>. 现在,所有这些类都包含方法m()。在我的 A 类中,这是我唯一可以访问的类,因为其他类仅在运行时可用,
我有一个 UIViewController 类 A 和 B。 A 使用以下方式加载 B:[A.view addSubView B.view]。 B 有一个带有“后退”按钮的导航栏。我想在单击时返回到
我有以下(第三方)类结构。我们将调用第三方项目 ProjectSeriously,并注意我使用 System.out.println 代替其他复杂的功能(100 行代码) . class A {
在下面的代码中,我从 Game 扩展了 MyGame。我有两个问题: 我们是否需要为所有render()、dispose()、pause()调用super方法 和 resize(w,h)?很多人都没有
例如,假设我想在调用 super.viewDidLoad() 时跳过一级。所以我希望能够做这样的事情: override func viewDidLoad() { super.super.vi
public class Faculty extends Employee { public static void main(String[] args) { new Fac
假设我有: class Superclass { //fields... methodA() {...} methodB() {...} ... } class Subclass exte
这个问题在这里已经有了答案: Why is super.super.method(); not allowed in Java? (22 个答案) 关闭 9 年前。 我怀疑我想做的事情是否可行。我有
我有一个实现 Initializable 的类。 public abstract class ExampleClass implements Initializable { public vo
我想知道,我有这个大数组,是否可以只在内存中使用一次而不是每个线程一次?以 stackoverflow 上的标签为例。他们几乎从不改变,为什么不为他们留下一个内存点呢?甚至可能将该数组永久保存在内存中
假设这三个类具有这个简单的层次结构: class A { func foo() { print("A") } } class B: A { override fu
有没有办法在 TypeScript 中调用 super.super.methodName。我想避免调用super.methodName,但我想调用二祖的methodName方法。 谢谢。 最佳答案 T
这个问题已经有答案了: When do I use super()? (11 个回答) 已关闭 7 年前。 package Geometry; public abstract class Geomet
我必须执行and()在我的实现 Predicate 的业务对象上. 出现问题的代码是 and() 行调用: Predicate predicate = new M
我有一个实现接口(interface)的抽象父类(super class): public abstract class FooMatrix implements Matrix { publi
我有四个 UIView:viewA 是 Root View ,它有 viewB 作为它的 subview 。 viewB 将 viewC 作为其 subview ,而 viewC 将 viewD 作为
有什么区别: class Child(SomeBaseClass): def __init__(self): super(Child, self).__init__() 和:
我有一个通用接口(interface) interface ListList extends List> .由于某些原因,我无法转换 ListList至 List> .有什么方法可以做到吗?为什么它不
我想调用带有两个参数的父类(super class)的构造函数,所以我调用了 super(arguments),但是编译器说: “类 Person 中的构造函数 Person 不能应用于给定类型; 要
我是一名优秀的程序员,十分优秀!