java如何编写适当的OOP代码以避免字段初始化问题?
运行这段代码将打印null
public class Weird {
static class Collaborator {
private final String someText;
public Collaborator(String text) {
this.someText = text;
}
public String asText() {
return this.someText;
}
}
static class SuperClass {
Collaborator collaborator;
public SuperClass() {
initializeCollaborator();
}
protected void initializeCollaborator() {
this.collaborator = new Collaborator("whatever");
}
public String asText() {
return this.collaborator.asText();
}
}
static class SubClass extends SuperClass {
String someText = "something";
@Override
protected void initializeCollaborator() {
this.collaborator = new Collaborator(this.someText);
}
}
public static void main(String[] arguments) {
System.out.println(new Weird.SubClass().asText());
}
}
(这里也是GitHub Gist)
现在,我知道了为什么会发生这种情况(这是因为超类的字段被初始化,然后在子类的字段被初始化之前调用了超类的构造函数)
问题是:
- 这里的设计问题是什么?从面向对象的角度来看,这种设计有什么问题,以至于结果在程序员看来很奇怪?这种设计突破了什么OOP原则李>
- 如何进行重构,使其不会工作“怪异”,并且是正确的OOP代码李>
# 1 楼答案
这种设计有什么问题:从构造函数调用实例方法,然后在子类中重写它。不要那样做。理想情况下,只能从构造函数体调用私有或最终实例方法,或静态方法。您还将在
SuperClass
之外公开一个字段(这是一个实现细节),这不是一个好主意——但是编写一个受保护的setCollaborator
方法并从initializeCollaborator
调用它会产生同样的问题至于如何解决这个问题,目前还不清楚你想要实现什么。你为什么需要
initializeCollaborator
方法呢?解决这个问题的方法多种多样,但它们实际上取决于你是否清楚地知道你想要实现什么。(见鬼,在某些情况下,最好的解决方案是一开始就不使用继承。更喜欢组合而不是继承,等等:)