从基类设置派生类成员

时间:2012-10-08 03:13:37

标签: java design-patterns

这是一个人为的例子:(在实际代码中使用的命名方案太混乱了)

我有一个班级父亲,扩展了祖父,这是第三方图书馆的一部分,无法改变。我也有一些课程延伸父亲;儿子,例如。祖父有一个看起来像这样的构造函数:

public Grandfather(String name) {...}

这个构造函数中实际发生的事情并不重要。重要的是,无论它做什么,也必须由所有派生类完成,因此对super(String)的调用是每个派生类'构造函数的强制性第一行。这里的含义是,祖父的所有后代的构造函数,无论移除多远,都必须始终调用super(或称为super的链式构造函数)作为其第一行。

在我的Father实现中,我有一个方法configure(String xml),它解析xml文件并使用反射在实例中设置各种参数。其中一些参数在祖父中,一些在父亲中,一些甚至可能在儿子中。每次从父派生的类实例化时,都需要运行配置。我最初的想法是简单地将configure(String)的调用添加到我的父构造函数中,如下所示:

public Father(String name, String xml) extends Grandfather {
  super(name);
  configure(xml);
}

这适用于Granfather和Father实例化,但在Son实例化上分解,原因与在构造函数中调用可覆盖方法通常会分解的原因相同。考虑以下Son实现:

public class Son extends Father {
  private String occupation = "unknown";

  public Son(String name, String xml) {
    super(name, xml);
  }
}

以下是发生的事情:

  1. 使用new Son(String, String)实例化新的Son。
  2. Son(String, String)内,对super(String, String)进行了调用,即。 Father(String, String)
  3. Father(String, String) configure(String)内召唤。
  4. configure(String)找到<occupation>元素并使用反射调用setOccupation("Coal Miner")
  5. Father(String, String)退出并执行返回Son(String, String)
  6. 在Son退出之前,所有使用提供的默认值的成员都已设置(这在Java中构造函数的末尾内联)
  7. 职业被内联覆盖,并被设置为“未知”。
  8. 我想避免重复调用configure(String),因为这是一个可能很昂贵的操作,所以在每个构造函数的末尾添加一个对configure(String)的调用。 (这将导致configure(String)为Son实例调用两次,为第n代后代调用n次。

    我还想避免在实例化父亲或其任何后代之后手动调用configure(String)

    Son s = new Son(...);
    s.configure(...);
    

    工厂方法在这里可以很好地工作但是由于使用祖父实例的方式,这是不可能的。简而言之,我几乎从不会实例化这些类,并且无法访问代码。

    或换句话说,执行以下操作:

    Father f = new Father(...);
    

    会导致configure(...)被父构造函数同时调用一次{/ p>

    Son s = new Son(...);
    

    会导致configure(...)被Son构造函数一次调用。

    鉴于这些限制,任何人都可以想出实现目标的方法,还是我搞砸了?

1 个答案:

答案 0 :(得分:1)

从你的声明中看来,你并不是真的反对在ctor末尾显式调用configure。

那么,这种扭曲是否可以接受?

class GrandFather {
  GrandFather(String name, boolean configure) {
    // some init
    if (configure) {
      configure(name);
    }
  }

  GrandFather(String name) {
    this(name, true);
  }
}

class Father {
  Father(String name, boolean configure) {
    super(name, false);

    // some init
    if (configure) {
      configure(name);
    }
  }

  Father(String name) {
    this(name, true);
  }
}

class Son {
  Son(String name, boolean configure) {
    super(name, false);

    // some init
    if (configure) {
      configure(name);
    }
  }

  Son(String name) {
    this(name, true);
  }
}

这个想法是,每个继承的类调用在它们的构造函数中显式配置,但它要求父级不要自己配置。