繁体   English   中英

强制子类初始化变量

[英]Force a child class to initialize a variable

我有一个类Foo ,它有一个必须初始化的字段_customObject 我还有一个继承自Foo的类Bar

public abstract class Foo
{
    protected CustomObject _customObject;

    public Foo()
    {
        // Do stuff
    }
    // Other methods that use _customObject
}

public class Bar : Foo
{
    // Constructor and other methods
}

我无法在Foo初始化对象_customObject ,因为每个继承的子CustomObject都包含一个不同的CustomObjectCustomObject ,因此必须在每个子类中初始化它:

public class Bar : Foo
{
    public Bar()
    {
        _customObject = new CustomObjectInherited1();
    }
}


public class Baz : Foo
{
    public Baz()
    {
        _customObject = new CustomObjectInherited2();
    }
}

其他人将实现从Foo继承的新类,所以我想知道是否有一种方法可以显示构建时间中的错误,类似于未实现抽象方法时。 如果未初始化CustomObject ,则会因为使用_customObject变量而抛出NullReferenceException ,从而导致应用程序崩溃。

您可以向Foo构造函数添加参数:

public abstract class Foo
{
    protected CustomObject _customObject;

    public Foo(CustomObject obj)
    {
        // Do stuff
        _customObject = obj;
    }
    // Other methods that use _customObject
}

然后,您的派生类将被强制调用它,传入CustomObject或从中派生的东西:

public class Bar : Foo
{
    public Bar():base(new CustomObjectInherited1())
    {

    }
}

不调用基础构造函数将导致编译时错误。 这并不完全保护你,因为有人仍然可以将null传递给基础构造函数,但至少他们会解释为什么他们在运行时获得NullReferenceError

您可以通过创建一个抽象方法来强制它,该方法要求子类覆盖它。

public abstract class Foo
{
    protected abstract CustomObject CreateCustomObject();
}

public class Bar : Foo
{
    protected override CustomObject CreateCustomObject()
    {
        return new BarCustomObject();
    }
} 

或者我最喜欢的解决方案:通过通用约束强制执行它。

public abstract class Foo<T> : where T : CustomObject, new()
{
    protected T _customObject;
    public Foo()
    {
        this.CustomObject = new T();
    }
}

public class Bar : Foo<BarCustomObject>
{
}

“James Thorpe”提供的答案是正确的(我已经提出了它),但我想在这里分享另一个选项:你可以将你的类标记为抽象,并引入一个抽象属性而不是“_customObject”字段。 这样,至少第一个初始化程序将被强制实现它。 缺点是你将放松后续级别子类的强制执行:

public abstract class Foo
{
    protected abstract CustomObject CustomObject {get; }

    public Foo()
    {
        // Do stuff
    }
    // Other methods that use _customObject
}

public class Bar : Foo
{
    // Constructor and other methods

    protected override CustomObject CustomObject
    {
        get { return "X"; }
    }
}

此外,使用第一个解决方案,可以在构造函数中验证传入的值 - 但是,这将是运行时验证。

暂无
暂无

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

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