Compositions
The primary means for handling complexity in object‑based systems is through object decomposition. An object can be composed of other objects or subobjects (nested objects). A subobject is an object defined within a parent object. The parent object (or owner) can delegate requests to be handled by its subobjects, and the subobjects can communicate back to their parent object.
Each of the subobjects knows the HomeHeatingSystem
as its parent,
and the HomeHeatingSystem
can access each of its subobjects by name. This view of
the HomeHeatingSystem
is called an object structure view, because it shows the
internal structure of the object. The subobjects can be linked to each other or not, depending on
the nature of the system.
With compositions, the parent object holds the subobjects by value rather than by pointer. The parent object is responsible for initializing and cleaning up after the subobjects. See Constructors and destructors for more information.
By default, a subobject designates a single instance and is implemented as a member of the structure of the parent object. The name of a member and type are the same as the name and type of the subobject. In other words, subobjects are embedded by value in the parent object, rather than as pointers to objects.
When a multiplicity of a subobject is specified as a number greater than one, the
subobjects are implemented as an array by default. For example, theFurnace
and
theRooms
are implemented as members of the HomeHeatingSystem
structure. The object theFurnace
is implemented as a single instance of type
Furnace
, and theRooms
are implemented as an array of three
Rooms
:
typedef struct HomeHeatingSystem HomeHeatingSystem;
struct HomeHeatingSystem {
RiCReactive ric_reactive;
/*** User implicit entries ***/
struct Furnace theFurnace;
struct Room theRooms[3];
};
If a multiplicity of a subobject is not known in advance, it is implemented as a
linked list. For example, if you specified multiplicity of theRooms
as
*
rather than 3, it would be implemented as an RiCList
as
follows:
struct HomeHeatingSystem {
RiCReactive ric_reactive;
/*** User implicit entries ***/
struct Furnace theFurnace;
RiCList theRooms;
};
You can also implement subobjects using other types of dynamic containers (such as
collections). You specify how to implement concrete relations using the
CG::Relation::Implementation
property. For example, setting the
Implementation
property for theRooms
to
UnboundedUnordered
would implement theRooms
as an
RiCCollection
rather than as an RiCList
or array.
The properties under the subject RiCContainers
determine how
functions are generated for various kinds of containers used to implement relations. See the
definitions provided for the properties on the applicable Properties tab of
the Features window.