简体   繁体   English

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

[英]Call abstract method from abstract class constructor

I would like to ask what are the risks of having something as follows: 我想问一下有什么风险如下:

abstract public class HtmlTemplateBuilder
{
    HtmlSource source;

    protected HtmlTemplateBuilder()
    {
        LoadTemplates();
    }

    public abstract void LoadTemplates();
}

The risk is if a derived class derives from the derived class: 风险是派生类派生自派生类:

DerivedClass2 -> #DerivedClass1 -> HtmlTemplateBuilder DerivedClass2 - >#DerivedClass1 - > HtmlTemplateBuilder

This can be solved by sealing #DerviedClass1, but are there any more risks or better practices for implementing this functionality? 这可以通过密封#DerviedClass1来解决,但实现此功能还有更多风险或更好的实践吗?

Thanks 谢谢

Have a look at this link which explains the perils with simple easy to understand examples 看看这个链接,通过简单易懂的例子来解释危险

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

I would remove the call to LoadTemplates from constructor and call Initialise on it when the templates actually need to be loaded and used. 我将从构造函数中删除对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();
}

The situation in which this pattern bit me is as follows: at some later stage you want to add a specialized HtmlTemplateBuilder , which can load different templates based on some criteria unknown to the class itself (maybe you decide you want some cool templates on a specific day of the year). 这个模式对我的情况如下:在稍后的某个阶段,你想要添加一个专门的HtmlTemplateBuilder ,它可以根据类本身未知的某些条件加载不同的模板(也许你决定要在特定的一些很酷的模板上一年中的某一天)。 That is: 那是:

public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
    private bool someCondition;

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

But how are you going to pass someCondition to the class? 但是,你怎么传递someCondition的类? The following won't work: 以下内容不起作用:

public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
    private bool someCondition;

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

    // ...
}

because the assignment of this.someCondition will be done after calling the base constructor, ie, after LoadTemplates() is called. 因为调用基础构造函数之后,即调用LoadTemplates() 之后 ,将完成this.someCondition的赋值。 Note that sealing derived classes does not solve this problem. 需要注意的是密封的派生类解决这个问题。

The way to solve this is as @Rahul Misra described: add an explicit Initialize method and call that after the constructor. 解决这个问题的方法是@Rahul Misra描述的:添加一个显式的Initialize方法并在构造函数之后调用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM