views:

92

answers:

4

Hi,

I'm curious as to what is good practice when it comes to certain scenarios involving nested types in .NET.

Lets say you have a Wheel class, and the Wheel class holds Bearing objects. A Bearing object only makes sense within a Wheel and you do not want to allow it to be created independently, so it would make sense to have the Bearing class nested inside the Wheel object. However, lets say you have a scenario where you now need to read a Wheel.Bearings property outside of the Wheel class. This would now require making the nested Bearing class public.

In this situation, what is the best option?
1 - Create a public Bearing class nested within the Wheel class
2 - Create an independent Bearing class which takes a Wheel object in its constructor
3 - Create a Wheel namespace and create an independent Bearing class inside this namespace.
4 - Something else?

UPDATE: I'm updating this with more details and to reflect some of the suggestions so far. ClassParent is the parent class, ClassChild is the child class. ClassChild is ALWAYS a child of ClassParent, it does not make sense to exist on its own. The problem is that ClassChild has a few properties that need to be exposed publically, while all the rest should only be called from ClassParent. An example is a ClassChild.Delete function which should not be exposed publically because it should only be called from ClassParent as ClassParent needs to perform appropriate cleanup and modifications.

After reviewing the suggestions, the design I've come up with looks a little unclean to me so I thought I'd ask for input. I have:

public class Parent
{
  ChildNested childObj

  public DeleteChild()
  {   
      //expose this method publically
      childObj.DeleteChild()
      //other functionality 
  }

  public Child GetChild()
  {
      //expose Child, not ChildNested publically
      return childObj
  }

   private class ChildNested:Child
   {
         public Child()
         {
              Base.Child()
         }
         public DeleteChild()
         {
              Base.Delete()
         }
   }

public abstract class Child
{
 protected Child()
     {
     }
 protected Delete()
     {
     }
     public PublicPropertyToExpose()
     {
     }    
}
+7  A: 

The best design here is to create a public Bearing class with an internal constructor, and create instances of it within the Wheel class.

If the Bearing class needs to access private members of the Wheel class, you can make the public Bearing class abstract, then make a concrete implentation as a private nested class inside of Wheel.

In general, you should not make public nested types.

SLaks
+1. I totally agree. Nested types are hard to read, hard to follow. When you program against them you always need to specify the out type, which is pretty annoying.
Steven
But what if the scenario was that Bearing can never and should never exist without a Wheel? Because in this case you can actually create a Bearing object without a Wheel. An example is a Keyboard class and a Key class, you can never have a keybody key without a keyboard.
MC.
+1  A: 
  • Create an independent Bearing class with private constructor
  • Create a factory class that will instantiate the Bearing class given a Wheel class
Darin Dimitrov
Alternatively have a method on wheel that returns a bearing, say "CreateBearing".
Cameron MacFarland
+1  A: 

I would like to test "Bearing" independently, so I would go for the 2nd option.

Robert
A: 

A Bearing can exist on its own, because its probably useful enough to be used elsewhere in the world, outside of a wheel.

A Wheel is aggregated by using Bearings, but a Wheel does not define a Bearing. Bearings are useful and can be used in other things besides wheels.

The fact that you need a public property for a Bearing indicates it needs to be a public class, outside of Wheel.

Also, what happens when you re-invent the Wheel (we all do...). Maybe you use a new "Air Bearing", such as exist in micro-turbines, now you have multiple Bearing types inside the Wheel class, some of which are not used.

I'd put the Bearing inside the same namespace, but not inside the Wheel class. Rarely do I find a need for inner classes. Usually an anonymous class fills in any gaps I need.

mrjoltcola