簡體   English   中英

初始化繼承類中的字段

[英]Initializing fields in inherited classes

在繼承的類中初始化常量或其他字段的最佳方法是什么? 我意識到此示例中有很多語法錯誤,但這是最好的示例,可以清楚地說明我要執行的操作。

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),但是就不能保證它們會被分配。 如果您將這些字段用作屬性並覆蓋它們,則仍需要初始化屬性的后備字段。 您將如何實施?

它抱怨一些語法錯誤:

  • 修飾語“抽象”在字段上無效。 嘗試改用屬性。 (#1)
  • const字段需要提供一個值(#1)
  • 修飾語“覆蓋”對此項目無效(#2)

如果基類要求派生類提供一個值,則兩種最常見的方法是:

在構造函數中需要它:

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

如果要在抽象類中包含特定字段,但又不想在基類中定義它們,則可以要求實現者通過構造函數提供值。

public abstract class MyClass
{
    private readonly double price;

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

使用這樣的基類,所有派生類都必須向基類的構造函數提供一個值,否則代碼將無法編譯。 這是一個看起來像的例子:

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

您得到的錯誤或多或少告訴您該怎么做。 您希望對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

您可以使用readonly內部構造函數來強制執行此行為,但是在某種程度上是不夠的。 如果您這樣做,則繼承者將需要位於相同的名稱空間/程序集中,以便利用內部構造函數。

另一個模型是創建虛擬的訪問器(屬性)。 這迫使派生類實現它。

這樣做的好處是“ canfly”的答案取決於一天中的(假設)時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM