1

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

我有一个类父亲,它扩展了祖父,它是无法更改的 3rdparty 库的一部分。我还有一些扩展父亲的类;以儿子为例。祖父有一个如下所示的构造函数:

public Grandfather(String name) {...}

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

在我的父亲实现中,我有一个configure(String xml)解析 xml 文件并使用反射在实例内设置各种参数的方法。其中一些参数在 Grandfather 中,有些在 Father 中,有些甚至可能在 Son 中。每次实例化从父亲派生的类时,都需要运行配置。我最初的想法是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. 一个新的 Son 使用new Son(String, String).
  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. 占用被内联覆盖并设置为“未知”。

我想避免重复调用,因为它可能是一个昂贵的操作,所以在每个构造函数的末尾configure(String)添加一个调用是不可行的。configure(String)(这将导致configure(String)Son 实例被调用两次,n 代后代被调用 n 次。

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

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

工厂方法在这里可以很好地工作,但由于使用 Grandfather 实例的方式,这是不可能的。长话短说,我几乎从来都不是实例化这些类并且零访问代码的人。

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

Father f = new Father(...);

将导致configure(...)被父亲构造函数调用一次,同时:

Son s = new Son(...);

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

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

4

1 回答 1

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);
  }
}

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

于 2012-10-08T03:57:08.877 回答