Как я выполняю некоторый код в суперклассе после того, как все подклассы были созданы?

Существует ли способ сделать это в C#? Я знаю, что подкласс назовет конструктора суперкласса прежде, чем вызвать его собственного конструктора, но чем, Если у меня есть некоторый код суперкласса, который должен только быть выполнен после того, как вызвали всех конструкторов подклассов?

7
задан Thiago de Arruda 30 April 2010 в 19:41
поделиться

5 ответов

Одним из способов достижения этого было бы перейти к 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();
  }
}
3
ответ дан 7 December 2019 в 05:19
поделиться

Вы можете сделать следующее, но это рискованно (см. Мое Правка ниже):

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();
    }
}
3
ответ дан 7 December 2019 в 05:19
поделиться

В языке C# нет ничего встроенного, что позволило бы вам это сделать. Однако использование шаблона создания может помочь в этом. Например, здесь может быть полезен паттерн Абстрактная фабрика. Базовая фабрика обеспечит вызов метода на вновь созданном базовом классе после его инстанцирования в качестве конкретного дочернего типа.

2
ответ дан 7 December 2019 в 05:19
поделиться
class A : B
{
   public A() : base()
   {
      base.doSomething();
   }
}

class B : C
{
   public B() : base()
   {

   }

   public void doSomething() { /* ... */ }
}

class C
{
   public C() { /* ... */ }
}

Порядок выполнения должен быть таким:

  1. C::ctor()
  2. B::ctor()
  3. A::ctor()
  4. B::doSomething()
0
ответ дан 7 December 2019 в 05:19
поделиться

Я не уверен, что вы имеете в виду - разве вы не можете просто вызвать код в суперклассе в конце нашего последнего конструктора подклассов? Кроме того, вы можете вызвать его непосредственно после создания экземпляра.

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
0
ответ дан 7 December 2019 в 05:19
поделиться