【问题标题】:Subclass of an Abstract class, always call Abstract constructor抽象类的子类,总是调用抽象构造函数
【发布时间】:2015-05-12 01:54:30
【问题描述】:

我有一个抽象类和一个子类

abstract class abstractClass
{
    public int x;

    protected abstractClass(int x)
    {
        this.x = x;
    }
}

class childClass : abstractClass
{
    childClass(int x)
        : base(x)
    {
    }
}

我有很多像这样的子类,所有这些类总是通过在它们的构造函数中调用 base(x) 来调用公共构造函数 abstractClass1(int x)

当我想向构造函数添加新属性时,例如另一个int y,我必须编辑所有这些类并将y 作为参数添加到每个子构造函数以及抽象类构造函数中。

考虑到我事先知道每个子类都将使用抽象类构造函数并且不会添加任何其他内容,还有其他方法吗?

【问题讨论】:

  • 取决于y 是什么。子类是否需要为y 提供值?只取x 的构造函数会继续有效吗?
  • @BJMyers 是的,当然y 将从构造函数中获取其值,否则我只需将y 添加到抽象类中就可以了
  • 您可以添加另一个带有额外参数的构造函数,或者在方法签名中将参数设置为默认值。

标签: c# constructor abstract-class


【解决方案1】:

这里有一个想法:创建一个AbstractClassParameters 类:

class AbstractClassParameters {
    public int x { get; private set; }
    // add more parameters here
    public AbstractClassParameters(int x) {
        this.x = x;
        // add more initializers here
    }
}

现在您可以将AbstractClassParameters 的实例传递给抽象类构造函数,每个子类都可以这样做,只需将其传递即可。

abstract class abstractClass
{
    public int x;

    protected abstractClass(AbstractClassParameters p)
    {
        this.x = p.x;            
    }
}

class childClass : abstractClass
{
    childClass(AbstractClassParameters p) : base(p) { }
}

添加参数时,您只需编辑AbstractClassParameters 类和abstractClass,而不是每个子类。

【讨论】:

  • 因此,每次将新字段/属性添加到抽象基类时,都需要扩展 AbstractClass AbstractClassParameters 的构造函数;并且每次调用 AbstractClassParameters 的构造函数都必须修改,而不是对 AbstractClass 的构造函数的调用次数相同。我看不出这实际上并没有增加支持扩展的工作量。
  • @PieterGeerkens 无论如何都必须修改调用站点(对子类 ctor 的调用),无论如何都必须修改基类。有一个要修改的新类,但不需要修改任何子类 - 因此工作量的减少应该与子类的数量成正比。
【解决方案2】:

不幸的是,我认为您无法以其他任何方式做到这一点。您必须修改抽象类,因为您必须添加新成员 y。您可以修改抽象类构造函数来初始化成员 y,也可以围绕 y 创建一个属性并让子类在构造函数中对其进行初始化。

【讨论】:

  • 我会修改抽象构造函数来初始化y值。但这仍然需要我为每个孩子修改childClass(int x, int y) : base(x,y)
【解决方案3】:

在我看来,大多数已经存在的子类都可以轻松地接受新属性 y 的默认值。在这种情况下,使用新的属性初始化器为基类添加一个新的构造函数,并让旧的构造函数将新属性的值设置为通用默认值。现在只有需要新属性的非默认值的子类才需要调用扩展的基类构造函数。

你的例子变成了:

abstract class abstractClass
{
    public int x { get; private set; }
    public int y { get; private set; }

    protected abstractClass(int x) : this(x, defaultY) {}
    protected abstractClass(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

class childClass : abstractClass
{
    childClass(int x)
        : base(x)
    {
    }
}

class childClass2 : abstractClass
{
    childClass(int x, int y)
        : base(x,y)
    {
    }
}

【讨论】:

  • 所有子类都必须设置y 值。没有默认值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2011-03-21
  • 2019-04-02
  • 1970-01-01
相关资源
最近更新 更多