Действительно ли мне нужно скопировать все конструкторы из Foo
в Bar
и Bah
? И затем, если я изменяю подпись конструктора в Foo
, нужно ли мне обновлять ее в Bar
и Bah
?
Да, если вы используете конструкторы для создания экземпляров.
Нет ли способа наследовать конструкторы?
Нет.
Нет ли способа поощрить повторное использование кода?
Ну, я не буду вдаваться в подробности, будет ли наследование конструкторов хорошим или плохим, и будет ли это стимулировать повторное использование кода, поскольку у нас их нет и мы не собираемся их получать. : -)
Но здесь, в 2014 году, с текущим C #, вы можете получить что-то очень похожее на унаследованные конструкторы, используя вместо этого универсальный метод create
. Это может быть полезным инструментом в вашем поясе, но вы не дотянетесь до него легко. Я достиг этого недавно, когда столкнулся с необходимостью передать что-то в конструктор базового типа, используемого в паре сотен производных классов (до недавнего времени базовый не нуждался в каких-либо аргументах, и поэтому конструктор по умолчанию был в порядке & mdash; производные классы вообще не объявляли конструкторы и получали автоматически предоставленный).
Это выглядит так:
// In Foo:
public T create<T>(int i) where: where T : Foo, new() {
T obj = new T();
// Do whatever you would do with `i` in `Foo(i)` here, for instance,
// if you save it as a data member; `obj.dataMember = i;`
return obj;
}
Это говорит о том, что вы можете вызывать универсальную функцию create
, используя параметр типа, который является любым подтипом Foo
, который имеет конструктор с нулевым аргументом.
Тогда вместо Bar b new Bar(42)
вы сделаете следующее:
var b = Foo.create<Bar>(42);
// or
Bar b = Foo.create<Bar>(42);
// or
var b = Bar.create<Bar>(42); // But you still need the <Bar> bit
// or
Bar b = Bar.create<Bar>(42);
Там я показал, что метод create
находится на Foo
напрямую, но, конечно, это может быть какой-то фабричный класс, если информация, которую он настраивает, может быть установлена этим фабричным классом.
Просто для ясности: имя create
не важно, оно может быть makeThingy
или как угодно.
Полный пример
using System.IO;
using System;
class Program
{
static void Main()
{
Bar b1 = Foo.create<Bar>(42);
b1.ShowDataMember("b1");
Bar b2 = Bar.create<Bar>(43); // Just to show `Foo.create` vs. `Bar.create` doesn't matter
b2.ShowDataMember("b2");
}
class Foo
{
public int DataMember { get; private set; }
public static T create<T>(int i) where T: Foo, new()
{
T obj = new T();
obj.DataMember = i;
return obj;
}
}
class Bar : Foo
{
public void ShowDataMember(string prefix)
{
Console.WriteLine(prefix + ".DataMember = " + this.DataMember);
}
}
}