当前位置: 首页 > 知识库问答 >
问题:

从基类设置派生类成员

满元凯
2023-03-14

下面是一个人为的例子:(实际代码中使用的命名方案太令人困惑)

我有一个班主任,他是第三方图书馆的一部分,不可更改。我也有一些课程延伸到父亲;比如儿子。祖父有一个类似这样的构造函数:

public Grandfather(String name) {...}

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

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

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

这对GrandFather和Father实例化很好,但在子实例化上会出现故障,原因与从构造函数中调用可重写方法通常会出现故障的原因基本相同。考虑以下子实施:

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

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

下面是发生的情况:

  1. 使用新子(String,String)实例化新子

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

我还想避免在实例化父亲或它的任何后代后手动调用配置(String)

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

工厂方法在这里可以很好地工作,但由于祖父实例的使用方式,这是不可能的。长话短说,我几乎从来都不是一个实例化这些类的人,也没有访问这些类的代码的权限。

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

Father f = new Father(...);

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

Son s = new Son(...);

将导致configure(…) 正被子构造函数调用一次。

考虑到这些限制,有人能想出一种方法来实现我的目标吗?还是我完蛋了?


共有1个答案

宋航
2023-03-14

从您的声明来看,您似乎并不真正反对在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);
  }
}

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

 类似资料:
  • 我仍然试图掌握抽象基类的概念,以及从派生类中可以做什么和不能做什么。 我有以下代码: 基类中的示例- 在派生类中

  • 我创建了Angular2 Typescript项目。我有很多表格,所以我想有一个类似基本组件的东西。 这是我的基本组件: 现在有我的子组件。我想从http获取所有项目,然后将其分配给基类 知道如何从订阅方法访问基字段吗?

  • 我理解您可以从派生类访问基类的成员,然而,我有一个函数需要指向我的基类作为一个整体的指针。例如: 有没有办法从派生类中获得指向这个基类的指针?

  • 派生类可以通过提供同样签名的新版本(如果签名不同,则是函数重载而不是函数重定义)重新定义基类成员函数。派生类引用该函数时会自动选择派生类中的版本。作用域运算符可用来从派生类中访问基类的该成员函数的版本。 常见编程错误 9.3 派生类中重新定义基类的成员函数时,为完成某些附加工作.派生类版本通常要调用基类中的该函数版本。不使用作用域运算符会由于派生类成员函数实际上调用了自身而引起无穷递归。这样会使系

  • 假设我有一个没有数据的类: 和派生类 Empty类的对象的大小为1。派生类的空部分的大小通常为0。据我所知,编译器看到基Empty类没有数据,因此它可以优化Empty的大小,以防它“在”Derived中,但标准并不要求这样做。 所以问题是: 我能在编译时确定Derived类的Empty部分并没有占用内存吗。 我知道我可以像一样进行检查...但它太冗长了,并且有几个类,如派生。有没有更优雅的解决方案

  • 一个类的对象经常会是另一个类的对象。例如,矩形当然是四边形(正方形、平行四边形和梯形也是这样),因此可以说矩形类 Rectangle 是从四边形类 Quadrilateral 继承而来的。在本例中,类 Quadrilateral 叫做基类,类 Rectangle 称为派生类。矩形是四边形的一种特殊类型,但是要说四边形是矩形则是不正确的。图 9.1 示例了几个简单的继承例子。 基类 派生类 stud