is there any way to make all derived classes count their instances?How (write code in one of C++, C#, Java)?
Imagine I've got access to the root class (e.g. object), and every other class is (directly or indirectly) derived from this class. What I want is:
AnyDerivedClass.InstancesCount()
Problem is, one must keep track of count in static variable, but it is not possible to "inject" static variable into derived class from base class, this holds only for member variables. That is, I have to write something like:
class object
{
private static int count = 0;
protected object() { ++count; }
protected ~object() { --count; }
public static InstancesCount() { return count; }
};
class derived : object
{
private static int count = 0;
public derived() { ++count; }
public ~derived() { --count; }
public static InstancesCount() { return count; }
}
This functionality is obviously repeated, and I cannot put it in base class. Note there are 2 ways of calculating: that if there are 7 instances of class derived1 and 8 instances of class derived2, there are (a) 15 instances of object or (b) 0 instances of object. I don't care which one, because I can't do neither (using reasonably practical means, e.g. imagine 100 classes, half of which are in library I cannot modify).
Of course, in theory it is possible to create map of (some run-type type identifier) => int count, and use ugly, slow, (run-time type)-based approach (at least in C#, Java).
Of course, if I can modify derived classes, I can use copy-paste (awful), macro (yeah I know), mixins (not in these languages) etc. But that is still real ugly.
This is specific problem, but It happened to me several times, that I'd like to be able to "inject" static member into derived class to solve problem elegantly.
Help much appreciated.
EDIT: thanks for good answer, in C++ it is possibly to use CRTP (Curiously recurring template pattern) as well, but not in C#/Java (no multiple inheritance). Of course, one must have access to derived classes and add this base class, so question remains (in case there is no other way, this looks best).
EDIT 2: looks impossible with current languages. static part of every class is not inheriting (and that's right), but there is no inheriting singleton associated with every class, so these kinds of problems cannot be solved so elegantly. To illustrate things, look at the following code: normal members and static members are current OOP languages feature, "singleton" (or whatever word would be) members are my suggestion/desire:
class Base
{
static int sMemberBase;
int memberBase;
//my wish (note that virtual for methods is allowed!):
singleton int singletonMemberBase;
};
class Derived : Base
{
static int sMemberDerived;
int memberDerived;
//my wish (note that virtual for methods is allowed!):
singleton int singletonMemberDerived;
};
//taken apart: (note: XYZStatic classes do not derive)
class Base { int memberBase; }
class BaseStatic { int sMemberBase; } BaseStaticInstance;
class Derived : Base { int memberDerived; }
class DerivedStatic { int sMemberDerived; } BaseStaticInstance;
//note: Derived::sMemberBase is compile-time changed to Base::sMemberBase
//my wish: (note inheritance!)
class BaseSingleton { int singletonMemberBase; } BaseSingletonInstance;
class DerivedSingleton : BaseSingleton { int singletonMemberDerived; } DerivedSingletonInstance;
If anything like that would be present in language, solution for my question would be simple and elegant:
//with singleton members, I could write counter like this:
class object
{
singleton int count;
object() { ++count; }
~object() { --count; }
};
In .Net, generics could be used to accomplish this. The following technique will not work in Java due to type erasure.
Now in your classes, be it base or subclasses, use it as follows:
You don't have to include the instance count property in every class either, it is only needed on the
InstanceCounter
class.Note: this sample does not require classes to inherit the instance counter class.
If one can afford to burn the one-superclass restriction in .Net, the following would also work:
Then retrieving the count:
or
Note2: As mentioned in the comments, using the finalizer (
~SomeClass
) is slow, and will only decrease the counter when the instance is actually collected by the GC. To get around this one would have to introduce deterministic "freeing" of instances, e.g. implementingIDisposable
.In C++, you can do it with a template base class. Basically it is a mixin, so it does still require each class to co-operate by inheriting from the mixin:
Since each class using the template has a different base class, it has a different
count
function and hence a different copy of the static variablecounter
.The trick of inheriting from a template class that's instantiated using the derived class as a template parameter is called CRTP.
In Java you can implement the counting function to the common super class of your hirachy.
This base class contains a Map - associating the classes to the number of instances. If a instance of base or one of its sub class is created, then the constructor ins invoked. The constructor increase the number of instances of the concreate class.
Way in C# that sprung in my mind imediately:
And how to use it:
The output could be done differently maybe. And its not pure OOP, but nor are C++ or Java examples in this thread. But it doesnt require a bit of code in inheriting class.
And dont forget about correcly disposing your objects!!
In Java you can use a global
Multiset
:Alternatively you can use a
Map<Class, Integer>
if you don't want the dependency on guava.Note: this only tracks instance creation, not garbage collection, so the count will never decrease. You can also track collection using
PhantomReference
s if you are willing to take a performance hit:It strikes me that if you if you actually want the injected/whatever class to actually do something useful then you must couple it in some way to the original classes, whether it's by inheritance or direct coupling with method calls. Otherwise you've just got two wheels spinning independently.
The only alternative I can think of is to use a factory pattern that can count creations for you -- but you'd have to hack something to count decrements, like handing the object back to the factory explicitly.