Можно ли принудительно выполнить контракт на компиляцию на производных классах, требующих реализации конструктора (с параметром)?
У меня есть базовый класс с конструктором, требующим параметр:
public class FooBase
{
protected int value;
public FooBase(int value) { this.value = value; }
public virtual void DoSomething() { throw new NotImplementedException(); }
}
Я хотел бы заставить деривации моего базового класса реализовать тот же самый конструктор:
public class Foo : FooBase
{
public Foo(int value) : base(value) { }
public override void DoSomething() { Console.WriteLine("Foo: {0}", value); }
}
Если конструктор не реализован, производные классы вызывают ошибку компилятора, потому что в базовом классе нет конструктора по умолчанию:
// ERROR: 'Does not contain a constructor that takes 0 arguments'
// Adding default constructor in FooBase eliminates this compiler error, but
// provides a means to instantiate the class without initializing the int value.
public class FooBar : FooBase
{
public override void DoSomething() { Console.WriteLine("FooBar: {0}", value); }
}
Добавление конструктора по умолчанию, FooBar(), в производном классе замалчивает ошибку компилятора, но обеспечивает опасное средство создания экземпляра FooBar без инициализации инициализированного значения инициализации базового класса. Поскольку я использую factory (см. Ниже), глушение ошибки компилятора приводит только к ошибке во время выполнения. Я хотел бы заставить FooBar реализовать FooBar (int)
ИНТЕРЕСНОЕ НАБЛЮДЕНИЕ:
Если конструктор по умолчанию FooBase() добавлен в FooBase, он наследуется производными классами, которые не предоставляют конструктор:
- Foo не наследует конструктор по умолчанию, поскольку он предоставляет явный конструктор.
- FooBar наследует FooBase().
ОДНАКО, то же самое не относится к конструктору non-default FooBase (int)!
- Foo ДОЛЖЕН явно реализовать FooBase (int) и базу вызовов (int).
- FooBar FAILS наследует конструктор не по умолчанию так же, как наследуется конструктор по умолчанию!
Мне не нужен конструктор по умолчанию в базовом классе, потому что экземпляры создаются с использованием метода factory, который предоставляет необходимый параметр "settings". Этот метод factory здесь не проиллюстрирован (который использует метод Activator.CreateInstance()).
Вот как создать производные классы:
static void Main(string[] args)
{
FooBase myFoo = new Foo(4); // Works, since Foo(int) is implemented.
// ERROR: 'Does not contain a constructor that takes 1 arguments'
FooBase myFooBar = new FooBar(9); // Fails to compile.
}
Потому что я использую factory - не прямое инстанцирование, как показано - ошибки компилятора нет. Вместо этого я получаю исключение во время выполнения: "Конструктор по типу не найден."
Нерабочие решения:
- Интерфейсы не поддерживают конструкторы.
- Конструкторы не могут быть виртуальными или абстрактными.
Похоже, что предоставление базового класса не может привести к заключению контракта с конструкторами.
Работа вокруг:
- Предоставить конструктор по умолчанию в базовом классе вместе с свойством для параметра параметров передачи.