Java 如何编写适当的OOP代码以避免字段初始化问题?
运行这段代码将打印null (这也是 现在,我知道了为什么会发生这种情况(因为在初始化子类的字段之前,先初始化了超类的字段,然后调用了超类的构造函数) 问题是:Java 如何编写适当的OOP代码以避免字段初始化问题?,java,oop,Java,Oop,运行这段代码将打印null (这也是 现在,我知道了为什么会发生这种情况(因为在初始化子类的字段之前,先初始化了超类的字段,然后调用了超类的构造函数) 问题是: 这里的设计问题是什么?从面向对象的角度来看,这种设计有什么错,以至于结果在程序员看来很奇怪?这种设计打破了什么OOP原则 如何进行重构,使其不会工作“怪异”,并且是正确的OOP代码 设计有什么问题:您从构造函数调用实例方法,然后在子类中重写它。不要那样做。理想情况下,仅从构造函数体调用私有或最终实例方法,或静态方法。您还将在超类之外公开
设计有什么问题:您从构造函数调用实例方法,然后在子类中重写它。不要那样做。理想情况下,仅从构造函数体调用私有或最终实例方法,或静态方法。您还将在
超类
之外公开一个字段(这是一个实现细节),这不是一个好主意-但是编写一个受保护的setCollaborator
方法并从initializeCollaborator
调用该方法会产生同样的问题
至于如何解决这个问题,目前还不清楚你想要实现什么。为什么您需要
初始化collaborator
方法?解决这个问题的方法有很多种,但它们实际上取决于你是否清楚地知道你想要实现什么。(见鬼,在某些情况下,最好的解决方案不是首先使用继承。更喜欢组合而不是继承,等等:)设计有什么问题:您从构造函数调用实例方法,然后在子类中重写它。不要那样做。理想情况下,仅从构造函数体调用私有或最终实例方法,或静态方法。您还将在超类
之外公开一个字段(这是一个实现细节),这不是一个好主意-但是编写一个受保护的setCollaborator
方法并从initializeCollaborator
调用该方法会产生同样的问题
至于如何解决这个问题,目前还不清楚你想要实现什么。为什么您需要
初始化collaborator
方法?解决这个问题的方法有很多种,但它们实际上取决于你是否清楚地知道你想要实现什么。(见鬼,在某些情况下,最好的解决方案不是一开始就使用继承。更喜欢组合而不是继承,等等:)与其使用initializeCollaborator方法,不如将协作器作为构造函数上的参数,并使用super调用它(新协作器(…)来自子对象。不要使用initializeCollaborator方法,而是将协作者设置为构造函数上的参数,并从子对象使用super(新协作者(..)调用它。我的设计问题是someText
字符串应该是协作者对象的显式依赖项(或“协作者”),或子类,或显式地是全局上下文的一部分(因此是共享上下文对象的常量或属性)
理想情况下,任一协作者都应该负责检索其依赖项;或者,如果子类对此负责,它应该将someText
作为依赖项(即使它总是初始化为相同的值),并且仅在设置someText时初始化Collaborator
从概念上讲,设计中对象之间的依赖关系对初始化施加了偏序。实现这种排序的机制应该在设计中始终是明确的,而不是依赖于Java语言的实现细节
一个(过度设计的)例子:
(现在请原谅,在写了一个名为
ConstantCollaboratorTextLocator
的东西之后,我需要站在瀑布下)我的设计问题是someText
字符串应该是collaborator对象或子类的显式依赖项(或“collaborator”),或者显式地是全局上下文的一部分(因此是共享上下文对象的常量或属性)
理想情况下,协作者应该负责检索其依赖项;或者,如果子类负责检索,则它应该将someText
作为依赖项(即使它总是初始化为相同的值),并且仅在设置someText时初始化协作者
从概念上讲,设计中对象之间的依赖关系要求对初始化进行部分排序。实现这种排序的机制在设计中应该始终是明确的,而不是依赖于Java语言的实现细节
一个(过度设计的)例子:
(现在请原谅,在写了一个名为
ConstantCollaboratorTextLocator
的东西之后,我需要站在瀑布下)@Belun:这还不足以帮助你找到最好的解决方案。我的意思是,大部分代码(我已经向你展示了),已经存在。这是遗留代码。我需要做的是为子类自定义协作器,同时保持与对超类相同的协作器(我的解决方案导致了这个问题)@Belun:好吧,如果你不想真正将其重构到正常状态,那么这几乎排除了你的问题2:)您能否在子类构造函数的主体内而不是通过重写的方法调用初始化协作者?在这一点上,您的子类将被“更多”初始化,因此您将处于一个更好的位置possible@Belun:这些信息并不足以帮助您找到最佳解决方案。我的意思是,大多数代码(我已经向您展示)已经存在。这是遗留代码。我需要做的是为子类定制Collaborator,同时让它与我为超类定制Collaborator时一样(我的解决方案导致了这个问题)@Belun:好吧,这差不多就是r
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());
}
}
interface ICollaboratorTextLocator {
String getCollaboratorText();
}
class ConstantCollaboratorTextLocator implements ICollaboratorTextLocator {
String text;
ConstantCollaboratorTextLocator(String text) {
this.text = text;
}
}
class SuperClass {
Collaborator collaborator;
public setCollaboratorTextLocator(ICollaboratorTextLocator locator) {
collaborator = new Collaborator(locator.getCollaboratorText());
}
SuperClass() {
setCollaboratorTextLocator(new ConstantCollaboratorTextLocator("whatever"));
}
}
class SubClass {
String text = "something";
SubClass() {
setCollaboratorTextLocator(new ConstantCollaboratorTextLocator(text));
}
}