Esta extensión es
EXPERIMENTAL_ Esto significa que el
comportamiento de esta extensión, los nombre de sus funciones y
en definitiva TODO lo documentado sobre esta extensión, puede
cambiar en una futura versión de PHP SIN AVISO_ La advertencia
queda hecha, y utilizar esta extensión queda bajo su propia
responsabiliad_
Introducción
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:
Ejemplo 1_ Class association
<?php
class DateTime {
function DateTime() {
// empty constructor
}
function now() {
return date("Y_m_d H:i:s");
}
}
class Report {
var $_dt = new DateTime();
// more properties ___
function Report() {
// initialization code ___
}
function generateReport() {
$dateTime = $_dt_>now();
// more code ___
}
// more methods ___
}
$rep = new Report();
?>
We can also associate instances at runtime by passing a reference in a
constructor (or any other method), which allow us to dynamically change
the association relationship between objects_ We will modify the example
above to illustrate this point:
Ejemplo 2_ Object association
<?php
class DateTime {
// same as previous example
}
class DateTimePlus {
var $_format;
function DateTimePlus($format="Y_m_d H:i:s") {
$this_>_format = $format;
}
function now() {
return date($this_>_format);
}
}
class Report {
var $_dt; // we'll keep the reference to DateTime here
// more properties ___
function Report() {
// do some initialization
}
function setDateTime(&$dt) {
$this_>_dt =& $dt;
}
function generateReport() {
$dateTime = $this_>_dt_>now();
// more code ___
}
// more methods ___
}
$rep = new Report();
$dt = new DateTime();
$dtp = new DateTimePlus("l, F j, Y (h:i:s a, T)");
// generate report with simple date for web display
$rep_>setDateTime(&$dt);
echo $rep_>generateReport();
// later on in the code ___
// generate report with fancy date
$rep_>setDateTime(&$dtp);
$output = $rep_>generateReport();
// save $output in database
// ___ etc ___
?>
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_
Ejemplos
We define 3 classes, each implementing a different storage method:
Ejemplo 3_ storage_classes_inc
<?php
class FileStorage {
var $data;
function FileStorage($data) {
$this_>data = $data;
}
function write($name) {
$fp = fopen(name, "w");
fwrite($fp, $this_>data);
fclose($data);
}
}
class WDDXStorage {
var $data;
var $version = "1_0";
var $_id; // "private" variable
function WDDXStorage($data) {
$this_>data = $data;
$this_>_id = $this_>_genID();
}
function store() {
if ($this_>_id) {
$pid = wddx_packet_start($this_>_id);
wddx_add_vars($pid, "this_>data");
$packet = wddx_packet_end($pid);
} else {
$packet = wddx_serialize_value($this_>data);
}
$dbh = dba_open("varstore", "w", "gdbm");
dba_insert(md5(uniqid("",true)), $packet, $dbh);
dba_close($dbh);
}
// a private method
function _genID() {
return md5(uniqid(rand(),true));
}
}
class DBStorage {
var $data;
var $dbtype = "mysql";
function DBStorage($data) {
$this_>data = $data;
}
function save() {
$dbh = mysql_connect();
mysql_select_db("storage", $dbh);
$serdata = serialize($this_>data);
mysql_query("insert into vars ('$serdata',now())", $dbh);
mysql_close($dbh);
}
}
?>
We then instantiate a couple of objects from the defined classes, and
perform some aggregations and deaggregations, printing some object information
along the way:
Ejemplo 4_ test_aggregation_php
<?php
include "storageclasses_inc";
// some utilty functions
function p_arr($arr) {
foreach($arr as $k=>$v)
$out[] = "\t$k => $v";
return implode("\n", $out);
}
function object_info($obj) {
$out[] = "Class: "_get_class($obj);
foreach(get_object_vars($obj) as $var=>$val)
if (is_array($val))
$out[] = "property: $var (array)\n"_p_arr($val);
else
$out[] = "property: $var = $val";
foreach(get_class_methods($obj) as $method)
$out[] = "method: $method";
return implode("\n", $out);
}
$data = array(M_PI, "kludge != cruft");
// we create some basic objects
$fs = new FileStorage($data);
$ws = new WDDXStorage($data);
// print information on the objects
echo "\$fs object\n";
echo object_info($fs)_"\n";
echo "\n\$ws object\n";
echo object_info($ws)_"\n";
// do some aggregation
echo "\nLet's aggregate \$fs to the WDDXStorage class\n";
aggregate($fs, "WDDXStorage");
echo "\$fs object\n";
echo object_info($fs)_"\n";
echo "\nNow let us aggregate it to the DBStorage class\n";
aggregate($fs, "DBStorage");
echo "\$fs object\n";
echo object_info($fs)_"\n";
echo "\nAnd finally deaggregate WDDXStorage\n";
deaggregate($fs, "WDDXStorage");
echo "\$fs object\n";
echo object_info($fs)_"\n";
?>
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_
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_
Tabla de contenidos
aggregate_info __
returns an associative array of the methods and properties from
each class that has been aggregated to the object_