#c_sharp #классы
Есть базовый абстрактный класс и 3 других класса, которые последовательно наследуют
реализацию предыдущего (BaseAbstract->A->B->C). При создании нового экземпляра одного
из этих трех классов, задействуется статическое поле (счетчик) в соответствующем классе
для подсчета суммарного количества экземпляров конкретного класса, вывод которого осуществляется
через статический метод.
abstract class BaseAbstract
{
public BaseAbstract()
{
//инициализация полей абстрактного класса
IncStaticField(); //вызов абстрактного метода в конструкторе абстрактного
класса
}
protected abstract void IncStaticField();
}
class A : BaseAbstract
{
private static int instNo = 0; //стат. поле
protected override void IncStaticField()
{
A.instNo = A.instNo + 1; //тип указываю здесь лишь для "пояснения" собственных
намерений
}
public static string Info() //вывод кол-ва созданных экземпляров конкретного
класса
{
return "Общее количество созданных экземпляров класса A: " + instNo;
}
}
class B : A
{
private static int instNo = 0;
protected override void IncStaticField()
{
B.instNo = B.instNo + 1;
}
public static new string Info() // замещение
{
return "Общее количество созданных экземпляров класса B: " + instNo;
}
}
class C : B
{
//аналогичная реализация, как в классе B
}
Данная реализация успешно подсчитывает кол-во созданных экземпляров для каждого класса
и выводит их значения через вызов метода Info() конкретного класса.
1) Насколько безопасным является вызов абстрактного (виртуального) метода в конструкторе,
благодаря которому и происходит увеличение статического поля конкретного класса?
2) Можно ли упростить реализацию метода IncStaticField(), дабы не приходилось объявлять
его в каждом классе лишь для указания класса статического поля которое следует увеличить?
Ответы
Ответ 1
Для начала пару слов про ваш код: public static new string Info() // замещение new в данном случае не требуется, т.к. CLR, вообще, и C#, в частности, не поддерживают наследование статических членов, соответственно никакой проблемы с одноименными статическими методами в классах наследниках не возникнет. 1) Насколько безопасным является вызов абстрактного (виртуального) метода в конструкторе, благодаря которому и происходит увеличение статического поля конкретного класса? Если абстрактный/виртуальный метод корректно реализован/переопределен с использованием override, то все будет нормально. Но проблема с вероятностью возникнет, если виртуальный метод не переопределен в классе и вызывает метод базового класса, который еще не был инстанцирован. Поэтому в целом такой подход не желателен, т.к. мы не можем заставить производный класс принудительно переопределить виртуальный метод. 2) Можно ли упростить реализацию метода IncStaticField(), дабы не приходилось объявлять его в каждом классе лишь для указания класса статического поля которое следует увеличить? Если метод используется исключительно для увеличения счетчика объектов, то почему бы не заменить его на обычный instNo++ в конструкторе? Таким образом определять метод в каждом классе не нужно. А вот более сложную логику, если она есть/нужна, уже можно выпилить в отдельный метод, и переопределять его по мере необходимости. Ну и напоследок полезная статья про статические члены классов и классы: Эрик Браун Семь советов по применению статических полей, методов и классовОтвет 2
Как вариант, могу предложить завести в самом базовом классе одно статическое поле -- словарь (Dictionary) с ключом -- тип класса либо название типа класса, и значением int. И один метод (невиртуальный), который и будет всё делать. В метод передаём Type. Принцип работы метода такой: увеличить счётчик в словаре для переданного типа, затем по reflection взять для этого типа тип-родитель, увеличить счётчик в словаре для него итд. Ну и обеспечить вызов этого метода-счётчика из конструктора каждого порождённого класса. Плюсы -- никаких виртуальных вызовов в конструкторе. Минусы -- использование рефлексии, снижающее производительность.
Комментариев нет:
Отправить комментарий