Существует ли способ сделать это в C#? Я знаю, что подкласс назовет конструктора суперкласса прежде, чем вызвать его собственного конструктора, но чем, Если у меня есть некоторый код суперкласса, который должен только быть выполнен после того, как вызвали всех конструкторов подклассов?
Одним из способов достижения этого было бы перейти к 2-фазной конструкции и инициализации. Таким образом, вы создаете экземпляры, а затем вызываете метод initialize, который вызывает базовый класс Initialize в соответствующем порядке
class MyBase
{
// Only if need to do some core initialization
public MyBase()
{
}
public virtual Initialize()
{
// do some initialization stuff here
}
}
class MyDerived : MyBase
{
// Only if need to do some core initialization
public MyDerived()
{
}
public override Initialize()
{
// do some initialization stuff here
// Call the base class initialization function
base.Initialize();
}
}
Вы можете сделать следующее, но это рискованно (см. Мое Правка ниже):
public class Parent
{
public Parent()
{
Initialize();
}
protected virtual void Initialize()
{
// do stuff
}
}
public class Child : Parent
{
protected override void Initialize()
{
// do child stuff
base.Initialize();
}
}
Править
Как предлагается в комментарии Терренса ниже, это - рискованный подход, поскольку Initialize ()
будет выполняться до выполнения конструктора Child
. Если есть какие-либо поля, инициализированные в конструкторе Child
, они не будут готовы, если они будут использоваться Initialize ()
. Это могло вызвать сбивающие с толку ошибки.
Простым решением было бы отказаться от родительского вызова Initialize ()
и вместо этого заставить дочерние классы вызывать Initialize ()
. Как предлагали другие, другим вариантом было бы использование абстрактного фабричного шаблона.
Вот простое решение, использующее статический фабричный метод:
class Program
{
static void Main()
{
Child.Create(() => new Child(5));
Console.ReadKey();
}
}
public abstract class Parent
{
protected virtual void Initialize()
{
Console.Write(" is the number.");
}
public static TChild Create<TChild>(Func<TChild> childGetter)
where TChild : Parent
{
var child = childGetter();
child.Initialize();
return child;
}
}
public class Child : Parent
{
private int _number;
public Child(int number)
{
_number = number;
}
protected override void Initialize()
{
Console.Write(_number.ToString());
base.Initialize();
}
}
В языке C# нет ничего встроенного, что позволило бы вам это сделать. Однако использование шаблона создания может помочь в этом. Например, здесь может быть полезен паттерн Абстрактная фабрика. Базовая фабрика обеспечит вызов метода на вновь созданном базовом классе после его инстанцирования в качестве конкретного дочернего типа.
class A : B
{
public A() : base()
{
base.doSomething();
}
}
class B : C
{
public B() : base()
{
}
public void doSomething() { /* ... */ }
}
class C
{
public C() { /* ... */ }
}
Порядок выполнения должен быть таким:
Я не уверен, что вы имеете в виду - разве вы не можете просто вызвать код в суперклассе в конце нашего последнего конструктора подклассов? Кроме того, вы можете вызвать его непосредственно после создания экземпляра.
class Program
{
static void Main(string[] args)
{
SubSub obj = new SubSub();
//obj.DoStuff();
Console.ReadLine();
}
}
class Super
{
public Super()
{
Console.WriteLine("Constructing Super");
}
public void DoStuff()
{
Console.WriteLine("Doin' stuff");
}
}
class Sub : Super
{
public Sub()
{
Console.WriteLine("Constructing Sub");
}
}
class SubSub : Sub
{
public SubSub()
{
Console.WriteLine("Constructing SubSub");
DoStuff();
}
}
Это приведет к выходу:
Constructing Super
Constructing Sub
Constructing SubSub
Doin' stuff