在基类构造函数中构造对象

本文关键字:对象 基类 构造函数 | 更新日期: 2023-09-27 18:08:17

我目前有以下代码模式,其中我在通用类MyClass的构造函数中初始化MyThing类型的特定对象。然而,在一些特定的派生类示例中(例如MySpecialClass),我想使用MyThing的派生版本,我将其命名为MySpecialThing。

public class MyClass
{
    public MyClass()
    {
        this.MyThing = new MyThing();
    }
    public MyThing MyThing { get; set; }
}
public class MySpecialClass : MyClass
{
    public MySpecialClass()
    {
        this.MyThing = new MySpecialThing();
    }
}

我的问题是这是否是不好的做法,因为实际上MyThing属性被初始化两次,一次在基类中,一次在派生类中。显然,我可以将一个布尔值传递给基类构造函数或其他东西,告诉它不要初始化MyThing,但这可能是多余的…

在基类构造函数中构造对象

这取决于创建MyThing需要多少开销。

然而,有一个解决方案:

你可以添加一个受保护的基类构造函数,它接受MyThing类型的参数,并在那里初始化它。

public class MyClass
{
    private readonly MyThing myThing;
    public MyClass(): this(new MyThing())
    {
    }
    protected MyClass(MyThing thing)
    {
        Contract.Requires(thing != null);
        myThing = thing;
    }
    public MyThing MyThing { get { return myThing; } }
}
public class MySpecialClass : MyClass
{
    public MySpecialClass(): base(new MySpecialThing())
    {
    }
}

我认为这是一种比在公共基类构造函数中添加bool值更好的方法。

我也认为这样做是值得的,即使构造MyThing的开销很小,因为它更清楚地表达了设计。

我还稍微改变了设计,使myThing成为一个只读字段,以表达它只应该在构建时设置的意图。(如果不是这种情况,并且您希望以后可以设置它,则必须恢复到公共属性setter。)

您关心性能还是可维护性?

性能问题只有在MyThing构造函数很昂贵,或者必须在紧密循环中创建大量对象时才有意义。

我更担心的是可维护性,因为你有多个初始化对象状态的地方。你可以把它从派生类传递给一个受保护的基类构造函数,并且有一个默认的构造函数默认使用MyThing

使用protected:

class BaseClass
{
    protected SomeType MyThing;
}