#c# #.net #constructor #abstract-class
#c# #.net #конструктор #абстрактный класс
Вопрос:
Я реализовал следующую структуру:
public abstract class A
{
protected A()
{
Test();
}
private void Test()
{
Console.WriteLine("2");
}
}
public class B : A
{
public B() : base()
{
Console.WriteLine("1");
}
}
Когда я создаю экземпляр класса B
, метод Test()
выполняется перед вызовом конструктора в классе B
. В моем случае этот метод должен выполняться после полной инициализации дочернего элемента. Возможным способом заставить его работать было бы сделать Test()
доступным из B
и вызвать его в конце его конструктора. Это сработало бы, но если кто-то создаст другой подкласс A
, есть вероятность, что он забудет вызвать метод. Мой вопрос заключается в том, существует ли более общее решение в базовом классе, чтобы убедиться, что метод выполняется после полной инициализации дочернего элемента.
Комментарии:
1. Это обычный запрос. Для этого в . Среда выполнения NET или язык C #.
Ответ №1:
Ответ — нет.
В него ничего не встроено .NET или C #, которые могут убедиться, что методы вызываются после выполнения всех конструкторов-потомков.
Другим подходом была бы некоторая форма фабричного шаблона, где ваш класс в основном просто предоставил бы вам другой экземпляр, который был правильно настроен, и все необходимые методы вызывались.
Ответ №2:
Это невозможно сделать, потому что инициализатор конструктора не работает таким образом. Скорее вы можете выбрать передачу некоторого параметра в базовый конструктор, параметры, которые могут быть специфичны для вашего дочернего класса, например
public abstract class A
{
protected A(string data)
{
Test(data);
}
private void Test(string data)
{
Console.WriteLine(data);
}
}
public class B : A
{
public B() : base("1")
{
//some other initialization logic here
}
}
Комментарии:
1. Это может быть делегат, который вызывается раньше
Test()
и содержит унаследованную инициализацию, специфичную для класса. Тогда унаследованный конструктор класса можно оставить пустым. Но некоторые функции (например, установка значения в авто-свойства только для геттера) не будут работать.
Ответ №3:
Вы не можете напрямую «вставить» вызов метода перед вызовом конструктора базового класса, потому что он вызывает метод для неинициализированного объекта. Но вы можете использовать шаблон метода шаблона:
abstract class A {
protected A () {
BeforeTest ();
Test ();
}
protected abstract void BeforeTest ();
private void Test () {
Console.WriteLine ("2");
}
}
class B : A {
protected override void BeforeTest () {
Console.WriteLine ("1");
}
}
internal class Program {
public static void Main (string [] args) {
new B ();
}
}
Кроме того, вы можете сделать Test
метод виртуальным:
abstract class A {
protected A () {
Test ();
}
protected virtual void Test () {
Console.WriteLine ("2");
}
}
class B : A {
protected override void Test () {
Console.WriteLine ("1");
base.Test ();
}
}
internal class Program {
public static void Main (string [] args) {
new B ();
}
}
Оба примера выдают один и тот же результат:
1
2