初始化继承类中的字段

Sen*_*ful 13 c# syntax inheritance field initialization

在继承类中初始化常量或其他字段的最佳方法是什么?我意识到这个例子中有很多语法错误,但这是解释我想要做什么的最好例子.

public abstract class Animal {
  public abstract const string Name; // #1
  public abstract const bool CanFly;
  public abstract double Price; // price is not const, because it can be modified

  public void Fly() {
    if (!CanFly)
      Debug.Writeln("{0}s can't fly.", Name);
    else
      Debug.Writeln("The {0} flew.", Name);
  }
}

public class Dog : Animal {
  public override const string Name = "Dog"; // #2
  public override const bool CanFly = false;
  public override double Price = 320.0;
}

public class Bird : Animal {
  public override const string Name = "Bird";
  public override const bool CanFly = true;
  public override double Price = 43.0;
}
Run Code Online (Sandbox Code Playgroud)

我想要完成的一些事情:

  • 基类必须分配这3个字段.
  • 理想情况下,我希望这些初始化字段位于类的顶部,这样我就可以看到我为每个类分配了哪些常量,并在需要时更改它们.
  • 名称和CanFly字段无法更改.

我知道你可以在构造函数中初始化这些字段(如果你摆脱了const),但是不能保证它们被分配.如果您将这些字段替换为属性并覆盖它们,则仍需要初始化属性的支持字段.你会如何实现这个?

它抱怨的一些语法错误:

  • 修饰符'abstract'在字段上无效.请尝试使用属性.(#1)
  • const字段需要提供一个值(#1)
  • 修饰符'覆盖'对此项无效(#2)

Rex*_*x M 21

如果基类需要派生类提供的值,则最常用的两种方法是:

在构造函数中需要它:

public readonly double Price;

protected BaseClass(double price)
{
    this.Price = price;
}
Run Code Online (Sandbox Code Playgroud)

派生类必须将价格传递给构造函数:

public Derived() : base(32)
{
}
Run Code Online (Sandbox Code Playgroud)

或者,使其成为一个抽象属性:

public abstract double Price { get; }
Run Code Online (Sandbox Code Playgroud)

派生类必须提供一些返回值的方法(尽管它们获取它的位置取决于派生类,在许多情况下它提供了更大的灵活性):

public override double Price
{
    get
    {
        return 32;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 抽象属性的潜在缺点是派生类可能会破坏“在生命周期内永不更改”的保证,这可以通过 readonly field + ctor 来强制执行。 (2认同)

Mar*_*ann 5

如果要在抽象类中包含特定字段,但又不想在基类中定义它们,则可以要求实现者通过构造函数提供值.

public abstract class MyClass
{
    private readonly double price;

    protected MyClass(double price)
    {
        this.price = price
    }
}
Run Code Online (Sandbox Code Playgroud)

使用这样的基类,所有派生类都必须为基类的构造函数提供值,否则代码将无法编译.这是一个可能看起来如何的例子:

public class Foo : MyClass
{
    public Foo() : base(42) { }
}
Run Code Online (Sandbox Code Playgroud)