Инициализация полей в наследованных классах

Что лучший способ состоит в том, чтобы инициализировать константы или другие поля в наследованных классах? Я понимаю, что в этом примере существует много синтаксических ошибок, но это - лучший пример для объяснения ясно, что я пытаюсь сделать.

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 поля.
  • Идеально я хотел бы, чтобы эти инициализированные поля были вместе наверху класса, таким образом, я вижу, какие константы я присвоил каждому классу, и измените их при необходимости.
  • Поля Name и CanFly не могут быть изменены.

Я знаю, что Вы могли инициализировать эти поля в конструкторе (если Вы избавляетесь от константы), но тогда они, как гарантируют, не будут присвоены. Если бы Вы имеете эти поля как свойства вместо этого и переопределяете их, необходимо было бы все еще инициализировать отступающее поле свойства. Как Вы реализовали бы это?

Несколько синтаксических ошибок это жалуется на:

  • Модификатор 'краткий обзор' не допустим на полях. Попытайтесь использовать свойство вместо этого. (#1)
  • Поле константы требует, чтобы значение было обеспечено (#1)
  • Модификатор 'переопределение' не допустим для этого объекта (#2)
13
задан Senseful 9 January 2010 в 00:05
поделиться

5 ответов

Если базовый класс требует, чтобы значение предоставлялось производным классом, два наиболее распространенных способа:

Требовать его в конструкторе:

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;
    }
}
21
ответ дан 1 December 2019 в 20:42
поделиться
[

]Если вы хотите иметь определенные поля в абстрактном классе, но не хотите определять их в базовом классе, вы можете потребовать, чтобы имплементаторы поставляли значения через конструктор. [

] [
public abstract class MyClass
{
    private readonly double price;

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

]С таким базовым классом все производные классы []должны [] поставлять значение в конструктор базового класса, иначе код не будет скомпилирован. Приведем один пример, как это может выглядеть:[

] [
public class Foo : MyClass
{
    public Foo() : base(42) { }
}
]
5
ответ дан 1 December 2019 в 20:42
поделиться
[

] Полученные ошибки более или менее говорят о том, что делать. Вы хотите использовать абстрактные свойства, а не поля, для []Name[] и []CanFly[], в то время как []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
]
2
ответ дан 1 December 2019 в 20:42
поделиться

Вы можете использовать Readly и Внутренний конструктор для обеспечения применения этого поведения, но это было бы несколько не хватало в Finese. Если вы идете с этим, наследники должны быть в том же пространстве имен / сборке, чтобы воспользоваться внутренним конструктором.

1
ответ дан 1 December 2019 в 20:42
поделиться

Другая модель состоит в том, чтобы создать аксессуар (свойство), который является виртуальным. Это заставляет полученные классы для его реализации.

Преимущество этого заключается в том, что «Canfly» может иметь ответ, который зависит от (сказать) время дня.

0
ответ дан 1 December 2019 в 20:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: