public abstract class Foo
{
protected readonly int Field;
protected Foo()
{
Field = 5;
}
}
public abstract class Bar:Foo
{
protected Bar():base()
{
Field = 5; //ошибка!!!
}
}
Код выше не компилируется по причине того, что Field readonly. Я понимаю, что конструктор это такой спец.
метод для создания объектов, соотв. readonly поля возможно менять(по сути давать значения) только
в этих спец. методах. Но почему бы не разрешить это также делать и наследникам, т.е. ограниченному числу
других спец. методов? Чем это плохо, что я упускаю из виду?
Здравствуйте, Sharov, Вы писали: S> Но почему бы не разрешить это также делать и наследникам, т.е. ограниченному числу других спец. методов?
В любом случае, есть ситуации когда не хочется давать наследникам такую возможность. Поэтому пришлось бы еще одно ключевое слово для такой возможности.
Но надо ли оно? Особенно если это не int, а большой объект. Базовый класс создает объект, а производный его выкидывает и перезаписывает — неэффективно.
Если создание объекта надо вынести наружу — этот объект можно передавать как параметр в конструктор базового класса.
Здравствуйте, Sharov, Вы писали:
S>Код выше не компилируется по причине того, что Field readonly. Я понимаю, что конструктор это такой спец. S>метод для создания объектов, соотв. readonly поля возможно менять(по сути давать значения) только S>в этих спец. методах. Но почему бы не разрешить это также делать и наследникам, т.е. ограниченному числу S>других спец. методов? Чем это плохо, что я упускаю из виду?
public abstract class Foo
{
protected int Field
{
get;
init;
}
protected Foo()
{
Field = 5;
}
}
public abstract class Bar : Foo
{
protected Bar() : base()
{
Field = 5; //нет ошибки
}
}
Здравствуйте, Silver_S, Вы писали:
S_S>В любом случае, есть ситуации когда не хочется давать наследникам такую возможность. Поэтому пришлось бы еще одно ключевое слово для такой возможности.
private?
S_S>Но надо ли оно? Особенно если это не int, а большой объект. Базовый класс создает объект, а производный его выкидывает и перезаписывает — неэффективно.
Эффективно\неэфективно судить должен разработчик соотв. классов (наследников), а создатели компилятора могли бы и предоставить
такую возможность.
Здравствуйте, Sharov, Вы писали:
S>в этих спец. методах. Но почему бы не разрешить это также делать и наследникам, т.е. ограниченному числу S>других спец. методов? Чем это плохо, что я упускаю из виду?
Переменная может быть задействована в некотором коде вызываемом из конструктора базового класса. Если инициализировать ее в наследнике, есть вероятность нарваться на дефольтное значение.
В таких случаях лучше задавать значение через параметр конструктора базового типа.
public abstract class Foo
{
protected readonly int Field;
protected Foo(int field)
{
Field = field;
}
}
public abstract class Bar : Foo
{
protected Bar() : base(5)
{
}
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
public abstract class Foo
{
protected readonly int Field;
protected Foo()
{
Field = 5;
}
}
public abstract class Bar : Foo
{
protected new readonly int Field;
protected Bar() : base()
{
Field = 15;
}
}
Здравствуйте, VladD2, Вы писали:
VD>Переменная может быть задействована в некотором коде вызываемом из конструктора базового класса. Если инициализировать ее в наследнике, есть вероятность нарваться на дефольтное значение.
Справедливо, с др. стороны, если возможно поломка инкапсуляции, зачем тогда делать переменную protected?