1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
COMMENT(note: name.sub is a module name, not a partition)
In the introduction section of this chapter it was stated that modules offer
new, conceptual features: modules offer program sections which are completely
separated from the rest of the program, but modules themselves can define
subsections (called hi(partition)em(partitions)) which can define components
(classes, types, variables, etc.) which are em(only) accessible to the module
and its partitions.
Within the restriction that partitions can be defined so that they're only
accessible to their module and their sibling-partitions the access rights of
em(classes) defined in partitions are identical to those of classes in
general: public members are accessible to their users, protected members are
available to classes derived from those classes, while private members cannot
be accessed from outside of those classes.
figure(modules/partition)
(Partitions of the `Math' module)
(MathPart)
Figure ref(MathPart) illustrates a simple module (tt(Math)) having two
partitions. It shows the relationships between the module and its partitions
in the same way as commonly used for classes: the most basic (least dependent)
partition is on top, the partition depending on the topmost partition is in
the middle, and the module itself, depending on both partitions, is at the
bottom. The tt(Math) module defines a class tt(Math), having a member
returning the sum of two tt(size_t) values and a member tt(count) returning
the number of performed additions. It's a very basic design merely
illustrating the way partitions are designed.
The object of tt(class Add) performs an addition, and the object of tt(class
Utility) keeps track of the number of additions that were performed.
Both tt(Add) and tt(Utility) are defined as classes in their own partitions:
tt(Math:Utility) and tt(Math:Add).
hi(partition: syntax) Note that partitions themselves are not classes. When
defining a emi(partition interface unit) only a single colon is used instead
of two, as used then defining cass member functions (so tt(Math:Utility) and
not tt(Mat::Utility)).
The tt(Math) interface unit exports tt(class Math), allowing code which does
not belong to the module tt(Math) itself to define tt(Math) objects after
importing the tt(Math) module:
verb( import Math;
void fun()
{
Math math;
...
}
)
Since the tt(class Math) has data members tt(Utility d_util) and tt(Add d_add)
these classes must be known inside the tt(Math) module interface unit
(tt(modmath.cc)), but also by software defining objects of tt(class Math)
(comparable to the requirement to, e.g., include tt(<string>) when a class
defines a tt(std::string) data member). Therefore the tt(Math) module
interface unit specifies tt(export import) for the tt(Utility) and tt(Add)
partitions. As we'll shortly see these tt(export) specifications do not imply
that software merely using the facilities of the tt(Math) module can also
define, e.g., tt(Math:Utility) objects: the partitions can still remain
`private' to the tt(Math) module. Here is the tt(Math) module interface unit,
defined in tt(math/modmath.cc):
verbinsert(-as4 examples/partition/math/modmath.cc)
The design of the module tt(Math) defining partitions introduces a completely
new level of separation: the components of partitions are like nested classes
but don't result in `class overpopulation': partitions are not defined
em(inside) modules but are completely separately defined from their modules,
while making their facilities em(only) available to their modules and sibling
partitions. And although probably not illustrating good design: by defining
tt(export) compounds in partition interface units the elements in those
compounds become directly available to using software essentially turning the
partition into a module.
|