#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 взять для этого типа тип-родитель, увеличить счётчик в словаре для него итд. Ну и обеспечить вызов этого метода-счётчика из конструктора каждого порождённого класса. Плюсы -- никаких виртуальных вызовов в конструкторе. Минусы -- использование рефлексии, снижающее производительность.
Комментариев нет:
Отправить комментарий