警告 |
|
In Object Oriented Programming, it is common
to see the composition of simple classes (and/or
instances) into a more complex one. This is a flexible
strategy for building complicated objects and object
hierachies and can function as a dynamic alternative to
multiple inheritance. There are two ways to perform class
(and/or object) composition depending on the relationship
between the composed elements:
Association
and
Aggregation
.
An
Association
is a composition of independently constructed and
externally visible parts. When we associate classes or
objects, each one keeps a reference to the ones it is
associated with. When we associate classes statically,
one class will contain a reference to an instance of the
other class. For example:
|
Aggregation
, on the other hand, implies encapsulation (hidding) of
the parts of the composition. We can aggregate classes by
using a (static) inner class (PHP does not yet support
inner classes), in this case the aggregated class
definition is not accessible, except through the class
that contains it. The aggregation of instances (object
aggregation) involves the dynamic creation of subobjects
inside an object, in the process, expanding the
properties and methods of that object.
Object aggregation is a natural way of
representing a whole-part relationship, (for example,
molecules are aggregates of atoms), or can be used to
obtain an effect equivalent to multiple inheritance,
without having to permanently bind a subclass to two or
more parent classes and their interfaces. In fact object
aggregation can be more flexible, in which we can select
what methods or properties to "inherit" in the aggregated
object.
We define 3 classes, each implementing a
different storage method:
|
We then instantiate a couple of objects
from the defined classes, and perform some aggregations
and deaggregations, printing some object information
along the way:
|
We will now consider the output to
understand some of the side-effects and limitation of
object aggregation in PHP. First, the newly created
$fs
and
$ws
objects give the expected output (according to their
respective class declaration). Note that for the
purposes of object aggregation,
private elements of a
class/object begin with an underscore character
("_")
, even though there is not real distinction between
public and private class/object elements in PHP.
$fs object Class: filestorage property: data (array) 0 = 3.1415926535898 1 = kludge != cruft method: filestorage method: write $ws object Class: wddxstorage property: data (array) 0 = 3.1415926535898 1 = kludge != cruft property: version = 1.0 property: _id = ID::9bb2b640764d4370eb04808af8b076a5 method: wddxstorage method: store method: _genid |
We then aggregate
$fs
with the
WDDXStorage
class, and print out the object information. We can see
now that even though nominally the
$fs
object is still of
FileStorage
, it now has the property
$version
, and the method
store()
, both defined in
WDDXStorage
. One important thing to note is that it has not
aggregated the private elements defined in the class,
which are present in the
$ws
object. Also absent is the constructor from
WDDXStorage
, which will not be logical to aggegate.
Let's aggregate $fs to the WDDXStorage class $fs object Class: filestorage property: data (array) 0 = 3.1415926535898 1 = kludge != cruft property: version = 1.0 method: filestorage method: write method: store |
The proccess of aggregation is
cummulative, so when we aggregate
$fs
with the class
DBStorage
, generating an object that can use the storage methods
of all the defined classes.
Now let us aggregate it to the DBStorage class $fs object Class: filestorage property: data (array) 0 = 3.1415926535898 1 = kludge != cruft property: version = 1.0 property: dbtype = mysql method: filestorage method: write method: store method: save |
Finally, the same way we aggregated
properties and methods dynamically, we can also
deaggregate them from the object. So, if we deaggregate
the class
WDDXStorage
from
$fs
, we will obtain:
And deaggregate the WDDXStorage methods and properties $fs object Class: filestorage property: data (array) 0 = 3.1415926535898 1 = kludge != cruft property: dbtype = mysql method: filestorage method: write method: save |
One point that we have not mentioned
above, is that the process of aggregation will not
override existing properties or methods in the objects.
For example, the class
FileStorage
defines a
$data
property, and the class
WDDXStorage
also defines a similar property which will not override
the one in the object acquired during instantiation
from the class
FileStorage
.