I have a bunch of classes which I have devised to represent my type hierachy. The problem is that they are "overly general" i.e. The constructors will accept combinations such as an array type which has two different element types without complaining (since it's just basically a tree). Are there good methods for hiding this generality from the rest of the system? In Java I suspect what I would do (since they are value objects which cannot change state) is have an interface/facade class which acts as a gate keeper to the rest of the classes and hide the remaining classes by sticking them inside a package and constraining them with package scope. The only way I can think of doing the same thing in C++ is to make the constructors private and use friend declarations. But is such use considered the greater of two evils? I.e. would it be better to just document the module indicating that they should be initialized through the facade?
Thanks for the reply. In this case it just eases the implementation. I.e. I implemented essentially a bunch of labelled nodes for types which are essentially an arbitrary tree structure. The debate in my mind at the moment is whether to give this tree structure an interface. The current interface is pretty primitive and just has a bunch of static factory methods associated with the the Type class to instantiate Type objects with various valid option combinations. This is a bit less than ideal since the get methods are still essentially tree-like. i.e. for a type array arguably you may want to have a getElement() method as a opposed to a getChild(0) method. Though I suspect given this is mostly cosmetic I will avoid writing an interface layer that just does pass through behavior.
When writing code that's basically exclusively for internal or otherwise expert use, it's kind of ok to not have a perfect interface and expect the user to be knowledgeable about what's going on. Interfaces need to be clear for things intended to be used by end-users. Documentation should make it clear that end-users shouldn't worry about this structure. If you try too hard to make things "perfect" from an end-user's perspective (when they don't care anyway!) you can end up making yourself jump through a whole lot of hoops for no real benefit.
In Java I suspect what I would do (since they are value objects which cannot change state) is have an interface/facade class which acts as a gate keeper to the rest of the classes and hide the remaining classes by sticking them inside a package and constraining them with package scope.
I do the same in C++, using a virtual base class as an interface, and it works well for me.
Thanks both. Trying not to worry about the "interface" design simplifies the code alot. I ended up simplifying the code to a single class with type codes (since I need them anyways) and running with that.