11

いくつかのフィールドと、これらのフィールドに作用するいくつかのメソッドを含む抽象基本クラスがあります。例えば:

public abstract class A
{
    protected double _field;

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

    ... some other abstract methods
}

Aのすべての子がコンストラクターで_fieldを初期化することを強制したい

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

    ... some other method implementations
}

これを達成するための正しいパターンは何ですか?

- 編集

私がやったことは:

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
}
4

4 に答える 4

13

派生クラスにフィールドを公開しないでください。代わりに、保護された抽象プロパティを作成します。

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

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

または、フィールドが特定のインスタンスに対して常に一定である必要がある場合は、それをコンストラクターパラメーターにして、プライベートに保ちます。

public abstract class A
{
    private readonly double _field;

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

    protected A(double field)
    {
        _field = field;
    }
}
于 2012-08-15T14:18:40.297 に答える
3

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)
    {
    }
}

補遺

コンストラクターで初期化を実行できない場合は、フィールドを抽象プロパティにすることができます。

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

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

これで、派生クラスはプロパティを実装する必要があるため、依存SquaredFieldプロパティの準備が整います。ただし、フィールドではなくなったため、名前を変更します。

于 2012-08-15T14:19:19.293 に答える
2

これは、フィールドのグループがそれ自体よりも緊密に結合されている可能性が高いAため、クラスに移動する必要があることを示している可能性がありAParamsます。

次にA、メソッドを宣言できますabstract protected AParams createParams()

于 2012-08-15T14:33:16.383 に答える
1

これを実現するために、別の抽象関数を使用できます。サブクラスはそれを実装することを余儀なくされます。

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...
    }
}
于 2012-08-15T14:26:08.740 に答える