How to represent the nested class of C++ in UML?
class A {
class B {
}
}
Nested class in UML (for any language) can be represented as:
Here
Class Inner1 is nested inside the outer class Outer 1
Classes Inner2, Inner3, Inner4 classes are nested inside Outer2
Reference taken from here
I had thought that the spec got away from the cross-and-circle notation. So, I did some wandering around in the specs, and couldn't find it in 2.0. I have to conclude that the 2.0 spec no longer supports it. While it's actually specified in v1.4, I looked all through the 2.4.1 spec, and it isn't anywhere to be seen (in fact, the word "anchor" returns 0 results in a document-wide search). I did some other looking around, and here's what I can piece together.
First, I had always understood that nested classes were a means of implementing composition. Furthermore, UML attempts to be implementation-agnostic, and nested classes aren't. (You can create composition in other ways, and not all OO languages support nested classes.) Now, 1.4's explanation includes this:
If Class B is attached to Class A by an “anchor” line with the “anchor” symbol on Class A, then Class B is declared within the Namespace of Class A. That is, the relationship between Class A and Class B is the namespace-ownedElement association.
Ok. Now UML 2.0 says this:
Kernel package represents the core modeling concepts of the UML, including classes, associations, and packages.
Here is a diagram of the Kernel package:
That's pretty abstruse, but have a look at the NamedElement abstract class at the top left. (A "NamedElement" class is an element that has a name.) Notice that Namespace derives from it. Now, notice on the right, directly to the right of the top of the Namespace class, there's another NamedElement class. One of the associations has the {subsets ownedElement} property on it, and a composition diamond on the Namespace end. On the Namespace end, there is the {subsets owner} property.
This means that NamedElement, when in composition association with Namespace, is a subset of Namespace. In other words, the relationship between Namespace and NamedElement is the namespace-ownedElement association described in the 1.4 spec. Therefore, the composition relationship, when adorned with the namespace and ownedElement properties, represents a nested (or inner, or internal, or whatever your favorite coding language calls it) class.
So, I'm going to say that this is the accepted 2.0 way to show nested classes if you are using composition notation. Like this:
Now, another way is to stick the nested class inside the containing class. The notation examples in the spec don't show this AFAICS, but they show it with other NamedElements (packages, components, etc.) so I don't see why you can't.
However, I don't see that the anchor notation is current. xmojmr's favorite site (and a good site, too), www.uml-diagrams.org, has this to say about it:
Now obsolete UML 1.4.2 Specification defined nested class as a class declared within another class and belonging to the namespace of the declaring class. Relationship between those classes was called "namespace owned element association
Nested classifier, e.g. nested class, nested interface, or nested use case could be used like any other classifier but only inside the containing class or interface.
Per UML 1.4.2 a declaring (nesting) class and a nested class could be shown connected by a line, with an "anchor" icon on the end connected to the declaring class. An anchor icon is a cross inside a circle.
UML 2.x specifications - including the recent UML 2.4.1 - describe nesting of classifiers within structured classes without providing explicit notation for the nesting. Note, that UML's 1.4 "anchor" notation is still used in one example in UML 2.4.x for packages as an "alternative membership notation" and without providing any other details or explanations.
I couldn't find that "one example" diagram, so maybe it's still around. But at the very least, the notation seems to be deprecated. I would either use the properties, create a <<nested>> stereotype, or put the nested class inside the owner class.
Nested classes may be displayed inside a compartment of the outer class.
Section 9.2.4.1 of the UML version 2.5.1 specification says:
If a Classifier has ownedMembers that are Classifiers, a conforming tool may provide the option to show the owned Classifiers, and relationships between them, diagrammatically nested within a separate compartment of the owning Classifier’s rectangle. (...) For example, a compartment showing the contents of the property nestedClassifier for a Class (see 11.4.2) shall be called “nested classifiers”.
Alternatively, nested classes may be displayed using the "circle-plus" notation:
Section 7.4.4.1 of the UML 2.5.1 specification says:
Conforming tools may optionally allow the “circle-plus” notation defined in sub clause 12.2.4 to show Package membership to also be used to show membership in other kinds of Namespaces (for example, to show nestedClassifiers).
(I have copied the image from the answer posted by #stamhaney)
Related
I'm new to c++ and I have more of a "design" question than actual code:
I'd like to write a program that works with many different types of graphs, however I want to support any type of vertex or weight (i.e the vertices are strings or char and the weight can be int,double or char or even a class).
For this cause I wrote a class template of graphs, which contains things like a set of vertices and a map with the edges and their weights and get/set functions - Then I have other classes such as finite-state machine graph, a regular weighted graph etc. which inherit from the class template "Graphs". (in each graph I know exactly what types the vertices and weights will be)
I did this as it seemed natural to expand upon a base class and inherit from it. It works so far, but then I thought whats the point? I could simple create in each class one of these generic graphs and use it as I would use an ADT from the STL.
The point being, is there any benefit to inheriting from a class template instead of just creating a new object of the template in the class (which itself isn't generic)?
According to the explanation you gave above it would be incorrect to inherit the generic graph. Inheritance is a tool to help expand an existing class of the same type to one with additional attributes, methods and functionality.
So, if all you're going to do is take the generic graph and make it a specific one by specifying the type of edges and weights without adding anything else to the structure or functionality of the original class then inheritance is unnecessary.
That being said, there are many cases for which one might need to inherit a template class and either keep it a generic one or a specific one depending on the task at hand. For example, if you were given the task of creating a class that represents a list of integers with the regular operations on lists and in addition to implement a function that return (let's say the average of these numbers or any other operation that is not supported by the original generic class List). In this case you inherit Class List and add your method.
Similarly, you could've kept the List as a template class and added the required functionality if that's what the task requires.
Your question is very broad and highly depends on your particular situation. Regardless, assuming that your question can be simplified to: "why should I use inheritance when I can just put the object inside the class?", here are two objective reasons:
Empty base optimization: if your base class X is empty (i.e. sizeof(X) == 0), then storing it as one of your derived class's fields will waste some memory as the standard forces every field to have its own address. Using inheritance will prevent that. More information here.
Exposing public methods/fields to the user of the derived class: if you want to "propagate" all your base class's public methods/fields to the derived one, inheritance will do that automatically for you. If you use composition, you have to expose them manually.
What would be the best representation of a C/C++ function pointer (fp) in an UML structural diagram?
I'm thinking about using an interface element, may be even if 'degenerate' with the constraint of having at most a single operation declared.
I found some proposal in this document: C and UML Synchronization User Guide, Section 5.7.4. But this sounds quite cumbersome and not very useful in practice. Even if right from a very low level of semantic view. Here's a diagram showing their concept briefly:
IMHO in C and C++ function pointers are used as such a narrowed view of an interface which only provides a single function and it's signature. In C fp's would be used also to implement more complex interfaces declaring a struct containing a set of function pointers.
I think I can even manage to get my particular UML tool (Enterprise Architect) to forward generate the correct code, and synchronizing with code changes without harm.
My questions are:
Would declaration of fp's as part of interface elements in UML proivde a correct semantic view?
What kind of stereotype should be used for single fp declaration? At least I need to provide a typedef in code so this would be my guts choice.(I found this stereotype is proprietary for Enterprise Architect) and I need to define an appropriate stereotype to get the code generation adapted. Actually I have chosen the stereotype name 'delegate', does this have any implications or semantic collisions?
As for C++, would be nesting a 'delegate' sterotyped interface with in a class element enough to express a class member function pointer correctly?
Here's a sample diagram of my thoughts for C language representation:
This is the C code that should be generated from the above model:
struct Interface1;
typedef int (*CallbackFunc)(struct Interface1*);
typedef struct Interface1
{
typedef void (*func1Ptr)(struct Interface1*, int, char*);
typedef int (*func2Ptr)(struct Interface1*, char*);
typedef int (*func3Ptr)(struct Interface1*, CallbackFunc);
func1Ptr func1;
func2Ptr func2;
func3Ptr func3;
void* instance;
};
/* The following extern declarations are only dummies to satisfy code
* reverse engineering, and never should be called.
*/
extern void func1(struct Interface1* self, int p1, char* p2) = 0;
extern int func2(struct Interface1* self, char*) = 0;
extern int func3(struct Interface1* self, CallbackFunc p1) = 0;
EDIT:
The whole problem boils down what would be the best way with the UML tool at hand and its specific code engineering capabilities. Thus I have added the enterprise-architect tag.
EA's help file has the following to say on the subject of function pointers:
When importing C++ source code, Enterprise Architect ignores function pointer declarations. To import them into your model you could create a typedef to define a function pointer type, then declare function pointers using that type. Function pointers declared in this way are imported as attributes of the function pointer type.
Note "could." This is from the C++ section, the C section doesn't mention function pointers at all. So they're not well supported, which in turn is of course due to the gap between the modelling and programming communities: non-trivial language concepts are simply not supported in UML, so any solution will by necessity be tool-specific.
My suggestion is a bit involved and it's a little bit hacky, but I think it should work pretty well.
Because in UML operations are not first-class and cannot be used as data types, my response is to create first-class entities for them - in other words, define function pointer types as classes.
These classes will serve two purposes: the class name will reflect the function's type signature so as to make it look familiar to the programmer in the diagrams, while a set of tagged values will represent the actual parameter and return types for use in code generation.
0) You may want to set up an MDG Technology for steps 1-4.
1) Define a tagged value type "retval" with the Detail "Type=RefGUID;Values=Class;"
2) Define a further set of tagged value types with the same Detail named "par1", "par2" and so on.
3) Define a profile with a Class stereotype "funptr" containing a "retval" tagged value (but no "par" tags).
4) Modify the code generation scripts Attribute Declaration and Parameter to retrieve the "retval" (always) and "par1" - "parN" (where defined) and generate correct syntax for them. This will be the tricky bit and I haven't actually done this. I think it can be done without too much effort, but you'll have to try it. You should also make sure that no code is generated for "funptr" class definitions as they represent anonymous types, not typedefs.
5) In your target project, define a set of classes to represent the primitive C types.
With this, you can define a function pointer type as a «funptr» class with a name like "long(*)(char)" for a function that takes a char and returns a long.
In the "retval" tag, select the "long" class you defined in step 4.
Add the "par1" tag manually, and select the "char" class as above.
You can now use this class as the type of an attribute or parameter, or anywhere else where EA allows a class reference (such as in the "par1" tag of a different «funptr» class; this allows you to easily create pointer types for functions where one of the parameters is itself of a function pointer type).
The hackiest bit here is the numbered "par1" - "parN" tags. While it is possible in EA to define several tags with the same name (you may have to change the tagged value window options to see them), I don't think you could retrieve the different values in the code generation script (and even if you could I don't think the order would necessarily be preserved, and parameter order is important in C). So you'd need to decide the maximum number of parameters beforehand. Not a huge problem in practice; setting up say 20 parameters should be plenty.
This method is of no help for reverse engineering, as EA 9 does not allow you to customize the reverse-engineering process. However, the upcoming EA 10 (currently in RC 1) will allow this, although I haven't looked at it myself so I don't know what form this will take.
Defining of function pointers is out of scope of UML specification. What is more, it is language-specific feature that is not supported by many UML modeling software. So I think that the general answer to your first question suggests avoiding of this feature. Tricks you provided are relevant to Enterprise Architect only and are not compatible with other UML modeling tools. Here is how function pointers is supported in some other UML software:
MagicDraw UML uses <<C++FunctionPtr>> stereotypes for FP class members and <<C++FunctionSignature>> for function prototype.
Sample of code (taken from official site -- see "Modeling typedef and function pointer for C++ code generation" viewlet):
class Pointer
{
void (f*) ( int i );
}
Corresponding UML model:
Objecteering defines FP attributes with corresponding C++ TypeExpr note.
Rational Software Architect from IBM doesn't support function pointers. User might add them to generated code in user-defined sections that are leaved untouched during code->UML and UML->code transformations.
Seems correct to me. I'm not sure you should dive into the low-level details of descripting the type and relation of your single function pointer. I usually find that description an interface is enough detalization without the need to decompose the internal elements of it.
I think you could virtually wrap the function pointer with a class. I think UML has not to be blueprint level to the code, documenting the concept is more important.
My feeling is that you desire to map UML interfaces to the struct-with-function-pointers C idiom.
Interface1 is the important element in your model. Declaring function pointer object types all over the place will make your diagrams illegible.
Enterprise Architect allows you to specify your own code generators. Look for the Code Template Framework. You should be able to modify the preexisting code generator for C with the aid of a new stereotype or two.
I have been able to get something sort of working with Enterprise Architect. Its a bit of a hacky solution, but it meets my needs. What I did:
Create a new class stereotype named FuncPtr. I followed the guide here: http://www.sparxsystems.com/enterprise_architect_user_guide/10/extending_uml_models/addingelementsandmetaclass.html
When I did this I made a new view for the profile. So I can keep it contained outside of my main project.
Modified the Class code templates. Basically selecting the C language and start with the Class Template and hit the 'Add New Stereotype Override' and add in FuncPtr as a new override.
Add in the following code to that new template:
%PI="\n"%
%ClassNotes%
typedef %classTag:"returnType"% (*%className%)(
%list="Attribute" #separator=",\n" #indent=" "%
);
Modified the Attribute Declaration code template. Same way as before, adding in a new Stereotype
Add in the following code to the new template:
%PI=""% %attConst=="T" ? "const" : ""%
%attType%
%attContainment=="By Reference" ? "*" : ""%
%attName%
That's all that I had to do to get function pointers in place in Enterprise Architect. When I want to define a function pointer I just:
Create a regular class
Add in the tag 'returnType' with the type of return I want
Add in attributes for the parameters.
This way it'll create a new type that can be included as attributes or parameters in other classes (structures), and operators. I didn't make it an operator itself because then it wouldn't have been referenced inside the tool as a type you can select.
So its a bit hacky, using special stereotyped classes as typedefs to function pointers.
Like your first example I would use a Classifier but hide it away in a profile. I think they've included it for clarity of the explaining the concept; but in practice the whole idea of stereotypes is abstract away details into profiles to avoid the 'noise' problem. EA is pretty good for handling Profiles.
Where I differ from your first example is that I would Classify the Primitive Type Stereotype not the Data Type stereotype. Data Type is a Domain scope object, while Primitive Type is an atomic element with semantics defined out side the scope of UML. That is not to say you cannot add notes, especially in the profile or give it a very clear stereotype name like functionPointer.
Is it me or the implementation of object oriented paradigm in C++ is missing the concept of class namespace?
Here is an example of what I mean:
Document { Header {} Body {} Footer {} }
Document is an object that can have a header, body, and footer.
A straight forward way to address such object and its elements from external namespace is
Document
Document::Header
Document::Body
Document::Footer
Is there a way to achieve such naming structure in C++ without imposing a restriction on the definition of Document class?
1) namespace Document { ... }
This case requires an object class inside its own namespace and using Document::Document seems redundant and unintended.
2) namespace Document { class ... } typedef Document::Document document;
This case gives document and Document::{part}, which in case sensitive language may seem weird and unrelated.
3) class Document { class ... };
This case requires including Document header in definition of every nested class and doesn't allow to make the final object be a derivative of its parts, since they are defined within its own scope.
4) class document { class ... }; class Document : public document {}
This case is close to what is intended but costs an extra class and inheritance.
!) Ideally, what I'd like to have is
namespace class Document {
class Header;
class Body;
class Footer;
class Document; // linked with the parent namespace as with its own name space
}
Document doc; // ok, resolves Document as a class
Document::{Part} docPart; // ok, resolves Document as namespace
.) Is there any other reasonable way to achieve what is intended without unreasonable extra cost?
I'm also not exactly sure why such trivial things are not a standard way to do it. :/ Any specific reason?
--- clarification ---
To address some of the raised questions,
"What is it useful for?" 1) Plain language 2) Transparent mapping from a language construct to an object's abstract model and vice versa.
"Why would one want to derive an object from its parts?" Not every entity introduced by an object has to be its part. It can be its essence, for example. E.g.:
Document { Skeleton{} Parts { Header {} Body {} Footer {} } }
--- abstract framework ---
Think of an object as a module whose definition may use external symbols and introduce some of its own along with the definition of its own logical entity, to which they should remain related since it introduces them.
--- point ---
The whole module is a definition of an object. It would be nice to be able to use it as such without any additional linguistic ridicules.
=== resolution ===
Thank you for your feedback.
Until there is a way in C++ to link a namespace name to a class, I guess I'll use the
ObjectName { ... Object {} } -> ObjectName::Object, ObjectName::Part
construct in such cases. It may be not as short as I'd like to, but at least transparent enough, with no extra cost, and can be used with forward declarations.
Your third option - using nested class declarations / definitions, will get you the ideal scope resolution as you want (though it will not involve a single namespace).
class Document
{
public:
class Header
{
// Header class declaration here
};
class Body
{
// Body class declaration here
};
class Footer
{
// Footer class declaration here
};
// Document declaration here.
};
Your concerns with that option are:
Requires including Document header in definition of every nested class
Yes - the nested classes are inextricably linked to the surrounding class, their implementations will depend on the definition of the surrounding class because it contains the definitions of the nested classes. This is unavoidable.
Dpesn't allow to make the final object be a derivative of its parts, since they are defined within its own scope.
What you are trying to do seems to make very little logical sense - you are trying to define something based on its own parts, which is a circular definition. What are you trying to achieve by deriving Document from Header, Body or Footer?
The final line of your question suggests that you find your desired functionality "trivial", but in my opinion and experience it is far from trivial. You seem to be conflating a namespace and a class because of syntactical similarities, but they are entirely different concepts. You have to separate the two in your mind, they have very little overlap besides some scoping effects and scope resolution syntax. Your "Document" must be either a namespace and a class. Pick one ;) (technically it's actually possible to have both a namespace Document and a class Document, but this is likely to be a source of confusion.
)
Your first case does exactly what you say you want. There's nothing redundant about Document::Document -- it refers to the Document class in the Document namespace. There might very well be a Document class in the XML namespace, and another one in the MyCompany namespace.
Your second case looks like an attempt to essentially defeat the purpose of using namespaces. If you don't want to use a namespace, don't -- just use the global (unspecified) namespace and risk collisions. If you only want to avoid the Document:: part in the code that's related to your Document class, add a using namespace Document directive in that code.
You just enclose the part classes within the Document class.
class Document {
public:
class Header;
class Body;
class Footer;
};
You can validly use this:
Document myDoc; // Type Document
Document::Header myHeader;
3) class Document { class ... };
This case requires including Document header in definition of every nested class and doesn't allow to make the final object be a derivative of its parts, since they are defined within its own scope.
No, this design is what makes the most sense. I don't understand what you think the difference would be between class and namespace class.
class Document
{
public:
class Header
{
};
Header m_header;
class Body
{
};
Body m_Body;
};
What's wrong with this design? You access the types via Document::Header. You access via instances like myDocument.m_header.
The only inherent oddness is that you can't name a type and member variable the same, but there are plenty of ways around that and it's a superficial restriction really.
Just because a Document object contains a Header object doesn’t mean that the Header class should be contained in the Document class. At least, that’s not usually done.
I would nest classes only in rare instances; namely, when the nested class is an implementation detail of the outer class, and isn’t exposed to the outside world (but even then it’s common to forego nesting).
This, by the way, is independent of C++: classes in general are rarely nested except to hide implementation details. Frameworks to model object relations as in your case wouldn’t normally use nesting. Instead, you might have something like this:
namespace Html {
class Document;
class Header;
class Body;
// …
}
C++ in particular uses flat namespace hierarchies but the above would equally apply to C# or Java.
Finally, to explicitly address your introductory question:
Is it me or the implementation of object oriented paradigm in C++ is missing the concept of class namespace?
C+ has this concept to the same extent as other modern OO languages: a class forms a namespace for the purpose of name lookup so you can achieve what you want. But for the reason mentioned above I don’t think it’s a particularly desirable goal.
It's not totally clear to me how much you want to expose the nested
classes, but if they are part of Document, they probably should be
nested classes. Your example of what you mean, at the start of your
code, is exactly how one would do this in C++:
class Document
{
public: // or not?
class Header
{
};
class Body
{
};
class Footer
{
};
};
About the only objection I can see is that implementation files only
concerned with Document::Header must include the entire Document
class definition, but I don't think this is a major problem; if
Document::Header really isn't independent, then it seems reasonable to
require this. With regards to your second objection to this solution:
you never want to make an object derive from its parts: a Document
hasA Header; it isn't an isA relationship.
If it does make sense for Header et al to be used separately, then the
best solution is to define them outside of the Document class, either
giving them more descriptive names (e.g. DocumentHeader) or wrapping
them in a special namespace (e.g. namespace DocumentParts). Depending
on their relationship with Document, it might make sense to use
typedef in Document so that they can be referred to as either
DocumentParts::Header or Document::Header.
I've recently seen several people doing things like this here on Stackoverflow:
class A:
foo = 1
class B:
def blah(self):
pass
In other words, they have nested classes. This works (although people new to Python seem to run into problems because it doesn't behave like they thought it would), but I can't think of any reason to do this in any language at all, and certainly not in Python. Is there such a usecase? Why are people doing this? Searching for this it seems it's reasonably common in C++, is there a good reason there?
The main reason for putting one class in another is to avoid polluting the global namespace with things that are used only inside one class and therefore doesn't belong in the global namespace. This is applicable even to Python, with the global namespace being a namespace of a particular module. For example if you have SomeClass and OtherClass, and both of them need to read something in a specialized way, it is better to have SomeClass.Reader and OtherClass.Reader rather than SomeClassReader and OtherClassReader.
I have never encountered this in C++, though. It can be problematic to control access to the outer class' fields from a nested class. And it is also pretty common to have just one public class in a compilation unit defined in the header file and some utility classes defined in the CPP file (the Qt library is a great example of this). This way they aren't visible to "outsiders" which is good, so it doesn't make much sense to include them in the header. It also helps to increase binary compatibility which is otherwise a pain to maintain. Well, it's a pain anyway, but much less so.
A great example of a language where nested classes are really useful is Java. Nested classes there automatically have a pointer to the instance of the outer class that creates them (unless you declare the inner class as static). This way you don't need to pass "outer" to their constructors and you can address the outer class' fields just by their names.
It allows you to control the access of the nested class- for example, it's often used for implementation detail classes. In C++ it also has advantages in terms of when various things are parsed and what you can access without having to declare first.
I am not a big fan of python, but to me this type of decisions are more semantical than syntactical. If you are implementing a list, the class Node inside List is not a class in itself meant to be used from anywhere, but an implementation detail of the list. At the same time you can have a Node internal class inside Tree, or Graph. Whether the compiler/interpreter allows you to access the class or not is in a different thing. Programing is about writing specifications that the computer can follow and other programers can read, List.Node is more explicit in that Node is internal to List than having ListNode as a first level class.
In some languages, the nested class will have access to variables that are in scope within the outer class. (Similarly with functions, or with class-in-function nesting. Of course, function-in-class nesting just creates a method, which behaves fairly unsurprisingly. ;) )
In more technical terms, we create a closure.
Python lets you do a lot of things with functions (including lambdas) that in C++03 or Java you need a class for (although Java has anonymous inner classes, so a nested class doesn't always look like your example). Listeners, visitors, that kind of thing. A list comprehension is loosely a kind of visitor:
Python:
(foo(x) if x.f == target else bar(x) for x in bazes)
C++:
struct FooBar {
Sommat operator()(const Baz &x) const {
return (x.f == val) ? foo(x) : bar(x);
}
FooBar(int val) : val(val) {}
int val;
};
vector<Sommat> v(bazes.size());
std::transform(bazes.begin(), bazes.end(), v.begin(), FooBar(target));
The question that C++ and Java programmers then ask themselves is, "this little class that I'm writing: should it appear in the same scope as the big class that needs to use it, or should I confine it within the scope of the only class that uses it?"[*]
Since you don't want to publish the thing, or allow anyone else to rely on it, often the answer in these cases is a nested class. In Java, private classes can serve, and in C++ you can restrict classes to a TU, in which case you may no longer care too much what namespace scope the name appears in, so nested classes aren't actually required. It's just a style thing, plus Java provides some syntactic sugar.
As someone else said, another case is iterators in C++. Python can support iteration without an iterator class, but if you're writing a data structure in C++ or Java then you have to put the blighters somewhere. To follow the standard library container interface you'll have a nested typedef for it whether the class is nested or not, so it's fairly natural to think, "nested class".
[*] They also ask themselves, "should I just write a for loop?", but let's suppose a case where the answer to that is no...
In C++ at least, one major common use-case for nested classes is iterators in containers. For example, a hypothetical implementation might look something like this:
class list
{
public:
class iterator
{
// implementation code
};
class const_iterator
{
// implementation code
};
};
Another reason for nested classes in C++ would be private implementation details like node classes for maps, linked lists, etc.
"Nested classes" can mean two different things, which can be split into three different categories by intent. The first one is purely stylistic, the other two are used for practical purposes, and are highly dependent on the features language where they are used.
Nested class definitions for the sake of creating a new namespace and/or organizing your code better. For example, in Java this is accomplished through the use static nested classes, and it is suggested by the official documentation as a way to create more readable and maintainable code, and to logically group classes together. The Zen of Python, however, suggests that you nest code blocks less, thus discouraging this practice.
import this
In Python you'd much more often see the classes grouped in modules.
Putting a class inside another class as part of its interface (or the interface of the instances). First, this interface can be used by the implementation to aid subclassing, for example imagine a nested class HTML.Node which you can override in a subclass of HTML to alter the class used to create new node instances. Second, this interface might be used by the class/instance users, though this is not that useful unless you are in the third case described below.
In Python at least, you don't need to nest the definitions to achieve either of those, however, and it's probably very rare. Instead, you might see Node defined outside of the class and then node_factory = Node in the class definition (or a method dedicated to creating the nodes).
Nesting the namespace of the objects, or creating different contexts for different groups of objects. In Java, non-static nested classes (called inner classes) are bound to an instance of the outer class. This is very useful because it lets you have instances of the inner class that live inside different outer namespaces.
For Python, consider the decimal module. You can create different contexts, and have things like different precisions defined for each context. Each Decimal object can assigned a context on creation. This achieves the same as an inner class would, through a different mechanism. If Python supported inner classes, and Context and Decimal were nested, you'd have context.Decimal('3') instead of Decimal('3', context=context).
You could easily create a metaclass in Python that lets you create nested classes that live inside of an instance, you can even make it produce proper bound and unbound class proxies that support isinstance correctly through the use of __subclasscheck__ and __instancecheck__. However, it won't gain you anything over the other simpler ways to achieve the same (like an additional argument to __init__). It would only limit what you can do with it, and I have found inner classes in Java very confusing every time I had to use them.
In Python, a more useful pattern is declaration of a class inside a function or method. Declaration of a class in the body of another class, as people have noted in other answers, is of little use - yes, it does avoid pollution of the module namespace, but since there_is_ a module namespace at all, a few more names on it do not bother. Even if the extra classes are not intended to be instantiated directly by users of the module, putting then on the module root make their documentation more easily accessible to others.
However, a class inside a function is a completely different creature: It is "declared" and created each time the code containing the class body is run. This gives one the possibility of creating dynamic classes for various uses - in a very simple way. For example, each class created this way is in a different closure, and can have access to different instances of the variables on the containing function.
def call_count(func):
class Counter(object):
def __init__(self):
self.counter = 0
def __repr__(self):
return str(func)
def __call__(self, *args, **kw):
self.counter += 1
return func(*args, **kw)
return Counter()
And using it on the console:
>>> #call_count
... def noop(): pass
...
>>> noop()
>>> noop()
>>> noop.counter
2
>>> noop
<function noop at 0x7fc251b0b578>
So, a simple call_counter decorator could use a static "Counter" class, defined outside the function, and receiving func as a parameter to its constructor - but if you want to tweak other behaviors, like in this example, making repr(func) return the function representation, not the class representation, it is easier to be made this way.
.
What are the pros and cons of using nested public C++ classes and enumerations? For example, suppose you have a class called printer, and this class also stores information on output trays, you could have:
class printer
{
public:
std::string name_;
enum TYPE
{
TYPE_LOCAL,
TYPE_NETWORK,
};
class output_tray
{
...
};
...
};
printer prn;
printer::TYPE type;
printer::output_tray tray;
Alternatively:
class printer
{
public:
std::string name_;
...
};
enum PRINTER_TYPE
{
PRINTER_TYPE_LOCAL,
PRINTER_TYPE_NETWORK,
};
class output_tray
{
...
};
printer prn;
PRINTER_TYPE type;
output_tray tray;
I can see the benefits of nesting private enums/classes, but when it comes to public ones, the office is split - it seems to be more of a style choice.
So, which do you prefer and why?
Nested classes
There are several side effects to classes nested inside classes that I usually consider flaws (if not pure antipatterns).
Let's imagine the following code :
class A
{
public :
class B { /* etc. */ } ;
// etc.
} ;
Or even:
class A
{
public :
class B ;
// etc.
} ;
class A::B
{
public :
// etc.
} ;
So:
Privilegied Access: A::B has privilegied access to all members of A (methods, variables, symbols, etc.), which weakens encapsulation
A's scope is candidate for symbol lookup: code from inside B will see all symbols from A as possible candidates for a symbol lookup, which can confuse the code
forward-declaration: There is no way to forward-declare A::B without giving a full declaration of A
Extensibility: It is impossible to add another class A::C unless you are owner of A
Code verbosity: putting classes into classes only makes headers larger. You can still separate this into multiple declarations, but there's no way to use namespace-like aliases, imports or usings.
As a conclusion, unless exceptions (e.g. the nested class is an intimate part of the nesting class... And even then...), I see no point in nested classes in normal code, as the flaws outweights by magnitudes the perceived advantages.
Furthermore, it smells as a clumsy attempt to simulate namespacing without using C++ namespaces.
On the pro-side, you isolate this code, and if private, make it unusable but from the "outside" class...
Nested enums
Pros: Everything.
Con: Nothing.
The fact is enum items will pollute the global scope:
// collision
enum Value { empty = 7, undefined, defined } ;
enum Glass { empty = 42, half, full } ;
// empty is from Value or Glass?
Ony by putting each enum in a different namespace/class will enable you to avoid this collision:
namespace Value { enum type { empty = 7, undefined, defined } ; }
namespace Glass { enum type { empty = 42, half, full } ; }
// Value::type e = Value::empty ;
// Glass::type f = Glass::empty ;
Note that C++0x defined the class enum:
enum class Value { empty, undefined, defined } ;
enum class Glass { empty, half, full } ;
// Value e = Value::empty ;
// Glass f = Glass::empty ;
exactly for this kind of problems.
One con that can become a big deal for large projects is that it is impossible to make a forward declaration for nested classes or enums.
If you're never going to be using the dependent class for anything but working with the independent class's implementations, nested classes are fine, in my opinion.
It's when you want to be using the "internal" class as an object in its own right that things can start getting a little manky and you have to start writing extractor/inserter routines. Not a pretty situation.
It seems like you should be using namespaces instead of classes to group like things that are related to each other in this way. One con that I could see in doing nested classes is you end up with a really large source file that could be hard to grok when you are searching for a section.
There are no pros and cons per se of using nested public C++ classes. There are only facts. Those facts are mandated by the C++ standard. Whether a fact about nested public C++ classes is a pro or a con depends on the particular problem that you are trying to solve. The example you have given does not allow a judgement about whether nested classes are appropriate or not.
One fact about nested classes is, that they have privileged access to all members of the class that they belong to. This is a con, if the nested classes does not need such access. But if the nested class does not need such access, then it should not have been declared as a nested class. There are situations, when a class A wants to grant privileged access to certain other classes B. There are three solutions to this problem
Make B a friend of A
Make B a nested class of A
Make the methods and attributes, that B needs, public members of A.
In this situation, it's #3 that violates encapsulation, because A has control over his friends and over his nested classes, but not over classes that call his public methods or access his public attributes.
Another fact about nested classes is, that it is impossible to add another class A::C as a nested class of A unless you are owner of A. However, this is perfectly reasonable, because nested classes have privileged access. If it were possible to add A::C as a nested class of A, then A::C could trick A into granting access to privileged information; and that yould violate encapsulation. It's basically the same as with the friend declaration: the friend declaration does not grant you any special privileges, that your friend is hiding from others; it allows your friends to access information that you are hiding from your non-friends. In C++, calling someone a friend is an altruistic act, not an egoistic one. The same holds for allowing a class to be a nested class.
Som other facts about nested public classes:
A's scope is candidate for symbol lookup of B: If you don't want this, make B a friend of A instead of a nested class. However, there are cases where you want exactly this kind of symbol lookup.
A::B cannot be forward-declared: A and A::B are tightly coupled. Being able to use A::B without knowing A would only hide this fact.
To summarize this: if the tool does not fit your needs, don't blame the tool; blame yourself for using the tool; others might have different problems, for which the tool is perfect.
paercebal said everything I would say about nested enums.
WRT nested classes, my common and almost sole use case for them is when I have a class which is manipulating a specific type of resource, and I need a data class which represents something specific to that resource. In your case, output_tray might be a good example, but I don't generally use nested classes if the class is going to have any methods which are going to be called from outside the containing class, or is more than primarily a data class. I generally also don't nest data classes unless the contained class is not ever directly referenced outside the containing class.
So, for example, if I had a printer_manipulator class, it might have a contained class for printer manipulation errors, but printer itself would be a non-contained class.
Hope this helps. :)
Remember that you can always promote a nested class to a top-level one later, but you may not be able to do the opposite without breaking existing code. Therefore, my advice would be make it a nested class first, and if it starts to become a problem, make it a top-level class in the next version.
For me a big con to having it outside is that it becomes part of the global namespace. If the enum or related class only really applies to the class that it's in, then it makes sense. So in the printer case, everything that includes the printer will know about having full access to the enum PRINTER_TYPE, where it doesn't really need to know about it. I can't say i've ever used an internal class, but for an enum, this seems more logical to keep it inside. As another poster has pointed out, it's also a good idea to to use namespaces to group similar items, since clogging the global namespace can really be a bad thing. I have previously worked on projects which are massive and just bringing up an auto complete list on the global namespace takes 20 minutes. In my opinion nested enums and namespaced classes/structs are probably the cleanest approach.
I agree with the posts advocating for embedding your enum in a class but there are cases where it makes more sense to not do that (but please, at least put it in a namespace). If multiple classes are utilizing an enum defined within a different class, then those classes are directly dependent on that other concrete class (that owns the enum). That surely represents a design flaw since that class will be responsible for that enum as well as other responsibilities.
So, yeah, embed the enum in a class if other code only uses that enum to interface directly with that concrete class. Otherwise, find a better place to keep the enum such as a namespace.
If you put the enum into a class or a namespace, intellisense will be able to give you guidance when you're trying to remember the enum names. A small thing for sure, but sometimes the small things matter.
Visual Studio 2008 does not seem to be able to provide intellisense for nested classes, so I have switched to the PIMPL idiom in most cases where I used to have a nested class. I always put enums either in the class if it is used only by that class, or outside the class in the same namespace as the class when more than one class uses the enum.
I can see a con for nested classes, that one may better use generic programming.
If the little class is defined outside the big one, you can make the big class a class template and use any "little" class you may need in the future with the big class.
Generic programming is a powerful tool, and, IMHO, we should keep it in mind when developing extensible programs. Strange, that no one has mentioned this point.
Only problem with nested classes that I bumped into yet was that C++ does not let us refer to the object of the enclosing class, in the nested class functions. We cannot say "Enclosing::this"
(But maybe there's a way?)