从抽象类构造函数中调用抽象方法

时间:2014-01-23 09:20:49

标签: c# oop abstract-class

我想问一下有什么风险如下:

abstract public class HtmlTemplateBuilder
{
    HtmlSource source;

    protected HtmlTemplateBuilder()
    {
        LoadTemplates();
    }

    public abstract void LoadTemplates();
}

风险在于派生类派生自派生类:

DerivedClass2 - > #DerivedClass1 - > HtmlTemplateBuilder

这可以通过密封#DerviedClass1来解决,但实现此功能还有其他风险或更好的做法吗?

由于

2 个答案:

答案 0 :(得分:1)

查看此链接,通过简单易懂的示例解释危险

https://blogs.msmvps.com/peterritchie/2012/04/25/virtual-method-call-from-constructor-what-could-go-wrong/

我会从构造函数中删除对LoadTemplates的调用,并在实际需要加载和使用模板时调用它上面的Initialise。

abstract public class HtmlTemplateBuilder
{
    HtmlSource source;
    object locker = new object();
    private bool initialised;

    protected HtmlTemplateBuilder()
    {
    }

    protected void Initialise()
    {
        lock (locker)
        {
            if(initialised)
            {
                LoadTemplates();
                initialised = true;
            }
        }
    }

    public abstract void LoadTemplates();
}

答案 1 :(得分:1)

这种模式对我的情况如下:在某个后期你想要添加一个专门的HtmlTemplateBuilder,它可以根据类本身未知的某些标准加载不同的模板(也许你决定了想要在一年中的特定日期获得一些很酷的模板。那就是:

public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
    private bool someCondition;

    public override void LoadTemplates()
    {
        if (someCondition)
        {
            LoadTemplatesSet1();
        }
        else
        {
            LoadTemplatesSet2();
        }
    }
}

但是你怎么把someCondition传给全班?以下内容不起作用:

public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
    private bool someCondition;

    public SpecialHtmlTemplateBuilder (bool someCondition)
    {
        this.someCondition = someCondition;
    }

    // ...
}

因为{/ 1}}的分配将在调用基础构造函数后完成,即 this.someCondition被调用后的。请注意,密封派生类确实解决了这个问题。

解决这个问题的方法是@Rahul Misra所描述的:添加一个显式LoadTemplates()方法并在构造函数之后调用它。