I’m not trying to say I know something everyone else doesn’t but I’ve been solving more and more designs with the use of nested classes, so I’m curious to get a feeling for the acceptablilty of using this seemingly rarely used design mechanism.
This leads me to the question: am I going down an inherintly bad path for reasons I’ll discover when they come back to bite me, or are nested classes maybe something that are underrated?
Here are two examples I just used them for: https://gist.github.com/3975581 – the first helped me keep tightly releated heirarchical things together, the second let me give access to protected members to workers…
2
I would not call this a “rarely used design mechanism” – at least, not universally: although there are shops where some contributors may frown upon using nested classes, this is not an obscure feature at all.
Although the existence of classes with assembly visibility and the introduction of lambdas has significantly reduced the need for nested classes*, they remain a valid design choice. Although there is some overlap with internal classes inside a namespace, the nested classes feature is unique in letting you hide a class entirely inside another class.
* The use of a similar feature in Java is much higher, because other alternatives available in C# are not there in Java.
2
Consider for a moment that you’re writing a class inside another class, that will never be used anywhere else in your program. Because if you were using it elsewhere, you’d make it an ordinary public class, just like all the others.
So the thing that is supposed to make OOP great (reusability) is absent here. Besides, what could you achieve with a nested class that you couldn’t achieve with ordinary methods and private members within the parent class?
For a useful software pattern utilizing nested classes, look here.
3
am I going down an inherintly bad path
I think in your second example (the worker subclasses) you definitely are. You have mapped each subclass to a specific state in the super class. So now each time you want to add a state to the super class you will need to make a change in three locations (add state to super class, add a new sub class, and change the constructor of derived class to add sub class to list).
The use of nested classes to access private members does appear to be a valid use (I have never personally done it) but your specific case does not work here.
As for the body part example. Because all of the nested classes are public you aren’t really doing much except namespacing. If these classes grow to include more functionality you may just find that the nested classes just clutter the interfaces and you are sifting through code to find something specific. I also notice that because you have nested classes you are forced to break naming conventions and name your classes with lower case (maybe this was a choice). But these arguments are more superficial than anything actually wrong.
Unless, of course, you needed to implement a disembodied arm. Then creating an arm by doing the following is confusing because there is no body/torso/side. (Also notice the confusing casing).
arm newArm = new Body.torso.side.arm("");
1
The only advantage I can think of nested classes is that they can be made private (or protected). I’d say in this case nested classes can help you encapsulate functionality if a class is intended to be used by the outer class and that class alone.
In my experience, nested classes
- Came back to haunt me
- Have been used when I wanted to cut corners
- Made testing a nightmare
- Had negative impact on separation of concerns and overall design
Had a brief look at your class, and right away I think that:
- It’s painful to look at it because the class is huge
- I can’t test “fingers” without pretty much creating entire body
- I can’t have multiple implementations of torso. Doesn’t seem that obvious in a “human body” context, but in a different scenario this would become obvious.
Why not separate your class into multiple classes and give them separate namespaces. E.g.
WindowsGame1.PhysicalModel.UpperBody
WindowsGame1.PhysicalModel.LowerBody
WindowsGame1.PhysicalModel.UpperBody.Arms