初始化继承类中的字段

时间:2010-01-08 23:49:21

标签: c# inheritance syntax initialization field

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

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

我正在努力完成的一些事情:

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

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

它抱怨的一些语法错误:

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

5 个答案:

答案 0 :(得分:21)

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

在构造函数中需要它:

public readonly double Price;

protected BaseClass(double price)
{
    this.Price = price;
}

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

public Derived() : base(32)
{
}

或者,将其设为抽象属性:

public abstract double Price { get; }

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

public override double Price
{
    get
    {
        return 32;
    }
}

答案 1 :(得分:5)

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

public abstract class MyClass
{
    private readonly double price;

    protected MyClass(double price)
    {
        this.price = price
    }
}

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

public class Foo : MyClass
{
    public Foo() : base(42) { }
}

答案 2 :(得分:2)

您获得的错误或多或少会告诉您该怎么做。您希望对NameCanFly使用抽象属性而不是字段,而Price则是普通属性。在派生类中,抽象属性在每种情况下都是只读的并返回一个常量。在代码中:

public abstract class Animal {
  public abstract string Name { get; }
  public abstract bool CanFly { get; }
  public double Price { get; set; }
  // etc
}

public class Dog : Animal {
  public override string Name { get { return "Dog"; } }
  public override bool CanFly { get { return false; } }
  public Dog() { Price = 320.0; }
}

// etc

答案 3 :(得分:1)

您可以使用readonlyinternal构造函数来强制执行此行为,但在finese中有点缺乏。如果你使用它,继承者需要在同一个命名空间/程序集中才能利用内部构造函数。

答案 4 :(得分:0)

另一个模型是创建一个虚拟的访问者(属性)。这会强制派生类实现它。

这样做的好处是'canfly'的答案可能取决于(比方说)一天中的时间。