Наследование в C# (Массивы обьектов)

Я немного упростил свой код чтоб мне могли обьяснить. Короче есть базовый клас Vegetable, и также Tomato, который наследуют базовый. Я создаю список типа Vegetable и добавляю туда обьекты типа Tomato, указывая в каждом количество помидорок (переменная quantity). Проблема заключаеться в конце, когда я пытаюсь вывести весь список обьектов с их соответствующим количеством. При дебаге увидел, что обьекты имеют 2 переменные:

quantity (Vegetable) [int]: 0 //это то, что выводит в конце

quantity [int]: 2 //тут как раз число, котороя я вводил

Обьясните, пожалуйста, почему в обьектах двое переменных, и как мне в конце вывести правильную переменную.

class Vegetable
{
   public int quantity;
}
class Tomato : Vegetable
{
   new public int quantity { get; set; }
}

class Program13
{
  static void Main(string[] args)
  {
  List<Vegetable> vegetableList = new List<Vegetable>();

  Tomato tomato1 = new Tomato();
  Console.WriteLine("Write quantity of tomatoes1");
  vegetableList.Add(tomato1);
  tomato1.quantity = Convert.ToInt32(Console.ReadLine());

  Tomato tomato2 = new Tomato();
  Console.WriteLine("Write quantity of tomatoes2");
  vegetableList.Add(tomato2);
  tomato2.quantity = Convert.ToInt32(Console.ReadLine());

  Console.WriteLine("Salad contains:");
  foreach (var obj in vegetableList)
  {
     Console.WriteLine($"{obj.quantity} {obj.GetType()}");
  }

} }

Выводит это: Salad contains:

0 Tomato
0 Tomato


Ответы (1 шт):

Автор решения: tym32167

вы используете "сокрытие", то есть ваше свойство new public int quantity { get; set; } как бы скрывает поле public int quantity; (см про оператор new). При сокрытии по сути оба quantity остаются, какой из них будет вызван зависит от типа переменной.

То есть вот тут myObject.quantity - если переменная myObject имеет тип Vegetable - то будет из него использоваться поле, если же myObject имеет тип Tomato - то оттуда.

Вообще это редко когда имеет смысл так делать. Обычно, если надо переопределить что то в производном классе, то в базовом это чтото (свойство или метод, например) объявляют виртуальными (virtual) и в производных классах уже перегружают (override). В этом случае тип переменной не важен, всегда будет вызываться код производного класса.

Пример

class Vegetable
{
    public virtual int quantity { get; set; }
}
class Tomato : Vegetable
{
    public override int quantity { get; set; }
}

Проверка

List<Vegetable> vegetableList = new List<Vegetable>();

Tomato tomato1 = new Tomato();
tomato1.quantity = 10;  
vegetableList.Add(tomato1);

Console.WriteLine("Salad contains:");
foreach (var obj in vegetableList)
{
    Console.WriteLine($"{obj.quantity} {obj.GetType().Name}");
}

Вывод

Salad contains:
10 Tomato

Конечно, пример искусственный, так как на практике нет смысла перегружать что то, если в перегрузке логика никак не отличается, но суть ясна я думаю.

→ Ссылка