简体   繁体   English

强制子类初始化字段

[英]Force child class to initialize fields

I have abstract base class that contains some fields and some methods that act on these fields. 我有抽象基类,包含一些字段和一些作用于这些字段的方法。 For example: 例如:

public abstract class A
{
    protected double _field;

    public double SquaredField { get { return _field * _field; } }

    ... some other abstract methods
}

I want to impose that all children of A initialize _field in their constructors 我想强制A的所有孩子在他们的构造函数中初始化_field

public class B : A
{
    public B(double field)
    {
         _field = Math.Sqrt(field);
    }

    ... some other method implementations
}

What's the correct pattern to achieve this? 实现这一目标的正确模式是什么?

-- EDIT - 编辑

What I ended up doing is: 我最终做的是:

public abstract class A
{
    protected readonly double _field;

    public A(double field)
    {
         _field = field;
    }

    public double SquaredField { get { return _field * _field; } }

    ... some other abstract methods
}


public class B : A
{
    public B(double field) : base(field)
    {
    }

    public static B CreateNew(double val)
    {
         return new B(Math.Sqrt(field));
    }

    ... some other method implementations
}

Don't expose a field to the derived classes at all. 根本不要将字段公开给派生类。 Instead, create a protected abstract property : 相反,创建一个受保护的抽象属性

public abstract class A
{
    protected double Field { get; }

    public double SquaredField { get { return Field * Field; } }
}

Or, if the field should always be constant for a particular instance, make it a constructor parameter and keep it private: 或者,如果字段对于特定实例应始终保持不变,请将其设为构造函数参数并将其保持为私有:

public abstract class A
{
    private readonly double _field;

    public double SquaredField { get { return _field * _field; } }

    protected A(double field)
    {
        _field = field;
    }
}

Don't let class A have a parameterless constructor: 不要让A类有一个无参数构造函数:

public abstract class A
{
    protected double _field;

    public double SquaredField { get { return _field * _field; } }

    // Require any fields that must be initialized in the base class's
    // constructor. If there are a lot of such fields, consider encapsulating
    // them all in their own class, e.g. AArgs.
    protected A(double field)
    {
        _field = field;
    }
}

public class B : A
{
    // You must call a base class constructor as below, because class A
    // no longer has a parameterless constructor to use by default.
    public B(double field)
        : base(field)
    {
    }
}

Addendum 附录

If you can't do the initialization in the constructor, you could make the field into an abstract property: 如果无法在构造函数中进行初始化,则可以将该字段设置为抽象属性:

public abstract class A
{
    protected abstract double Field { get; }

    public double SquaredField { get { return Field * Field; } }
}

Now, the derived class has to implement the property, so you'll have it ready for the dependent SquaredField property. 现在,派生类必须实现该属性,因此您可以为依赖的SquaredField属性做好准备。 I would change the name though, since they're not fields anymore. 我会更改名称,因为它们不再是字段了。

That's likely a signal that group of fields is more tightly coupled than A itself, and so should be moved to a class, say, AParams . 这可能是一组字段比A本身更紧密耦合的信号,因此应该转移到类,例如, AParams

Then in A you can declare an abstract protected AParams createParams() method. 然后在A您可以声明一个abstract protected AParams createParams()方法。

You could use a separate abstract function to accomplish this. 您可以使用单独的抽象函数来完成此任务。 The subclasses would be forced to implement it. 子类将被迫实现它。

public abstract class A
{
    protected double _field;

    protected A()
    {
        InitializeField();
    }

    protected abstract void InitializeField();

    public double SquaredField { get { return _field * _field; } }
}

public class B : A
{
    protected override void InitializeField()
    {
        // Initialize...
    }
}

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

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