LXX. Aggregation d'objets/Composition de fonctions

Avertissement

Ce module est EXPERIMENTAL . Cela signifie que le comportement de ces fonctions , leurs noms et concrètement , TOUT ce qui est documenté ici peut changer dans un futur proche , SANS PREAVIS ! Soyez-en conscient , et utiliser ce module à vos risques et périls .

Introduction

En programmation objet , il est courant de rencontrer la combinaison de classes simples ( et de leurs instances ) en une classe plus complexe . C' est une strategie habile pour mettre en place des objets complexes , et des hierarchies d 'objets . Ce système peut fonctionne comme une alternative dynamique à l ' héritage multiple . Il y a deux solutions pour combiner deux classes , suivant la relation de leurs éléments constitutifs : L' Association et l ' Aggregation .

Une Association est une combinaison d' éléments construits indépendamment et visibles à l 'extérieur . Lorsque nous associons des classes ou objets , chacun garde une référence à l' autre partie de l 'association . Lorsque nous associons des classes statiquement , une classe contient une référence à une instance de l ' autre classe . Par exemple :

Exemple 1 . Association de classe

 
?php

 
class

 
DateTime

 
{

 
function

 
DateTime(

 
)

 
{

 
/

 
/

 
constructeur

 
vide

 
   }

 
function

 
now(

 
)

 
{

 
return

 
date("Y-m-d

 
H:i:s")

 
;

 
   }

 
}

 
class

 
Report

 
{

 
var

 
$_dt

 
=

 
new

 
DateTime()

 
;

 
/

 
/

 
autres

 
propri

 
eacute;t

 
eacute;s

 
..

 
.

 
function

 
Report(

 
)

 
{

 
/

 
/

 
initialisation

 
du

 
code

 
..

 
.

 
   }

 
function

 
generateReport(

 
)

 
{

 
$dateTime

 
=

 
$_dt

 
-

 
now()

 
;

 
/

 
/

 
autre

 
code

 
   }

 
/

 
/

 
autres

 
m

 
eacute;thodes

 
..

 
.

 
}

 
$rep

 
=

 
new

 
Report()

 
;

 
?



Nous pouvons aussi associer des instances dynamiquement, en passant une référence au constructeur (ou par une autre méthode), ce qui permet de gérer dynamiquement l'association entre les objets. Nous allons modifier l'exemple ci-dessus pour illustrer ce point :

Exemple 2 . Association d ' objets

 
?php

 
class

 
DateTime

 
{

 
/

 
/

 
identique

 
au

 
pr

 
eacute;c

 
eacute;dent

 
exemple

 
}

 
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

 
;

 
/

 
/

 
Nous

 
allons

 
garder

 
la

 
r

 
eacute;f

 
eacute;rence

 
agrave

 
;

 
DateTime

 
ici

 
/

 
/

 
autre

 
propri

 
eacute;t

 
eacute;s

 
function

 
Report(

 
)

 
{

 
/

 
/

 
initialisation

 
   }

 
function

 
setDateTime

 
(

 
$dt

 
)

 
{

 
$this

 
-

 
_dt

 
=

 
$dt

 
;

 
   }

 
function

 
generateReport(

 
)

 
{

 
$dateTime

 
=

 
$_dt

 
-

 
now()

 
;

 
/

 
/

 
autre

 
code

 
..

 
.

 
   }

 
/

 
/

 
autres

 
m

 
eacute;thodes

 
..

 
.

 
}

 
$rep

 
=

 
new

 
Report()

 
;

 
$dt

 
=

 
new

 
DateTime()

 
;

 
$dtp

 
=

 
new

 
DateTimePlus("l

 
,

 
F

 
j

 
,

 
Y

 
(h:i:s

 
a

 
,

 
T)")

 
;

 
/

 
/

 
G

 
eacute;n

 
eacute;ratino

 
du

 
rapport

 
avec

 
une

 
simple

 
date

 
$rep

 
-

 
setDateTime

 
(

 
$dt)

 
;

 
echo

 
$rep

 
-

 
generateReport()

 
;

 
/

 
/

 
plus

 
loin

 
dans

 
le

 
code

 
/

 
/

 
generation

 
du

 
rapport

 
avec

 
une

 
date

 
design

 
eacute;e

 
$rep

 
-

 
setDateTime

 
(

 
$dtp)

 
;

 
$output

 
=

 
$rep

 
-

 
generateReport()

 
;

 
/

 
/

 
sauvegarde

 
pour

 
affichage

 
dans

 
la

 
base

 
/

 
/

 
..

 
.

 
etc

 
..

 
.

 
?





L' Aggregation , d'un autre coté , implique l 'encapsulation et le masquage des parties de la combinaison . Nous pouvons aggréger des classes en utilisant une méthode statique , grâce aux sous-classes ( mais PHP ne supporte pas bien les sous classes) , et dans ce cas , la définition de la classe aggrégée n 'est pas accessible , sauf via les méthodes de la classe contenant . L' aggregation d'instances (aggrégation d'objets ) implique la création dynamique de sous-objets à l'intérieur d'un autre objet , et dans le même temps , l'extension des capacités de l'objet principal (en terme de méthodes accessibles ) .

L' aggrégation d'object est une méthode naturelle pour représenter des relation de type tout-partie (par exemple , une molécule est une aggrégation d'atomes) , ou bien peut être utilisée pour obtenir un effet équivalent à l 'héritage multiple , sans avoir à lier plusieurs classes et leurs interfaces . En fait , les aggrégations d' objets sont plus souples , car nous pouvons alors sélectionner les méthodes et les propriétés qui sont transmises à l 'objet aggrégé .

Exemples

Nous définissons trois classes , qui implémentent chacune une méthode de stockage différente :

Exemple 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

 
;

 
/

 
/

 
variable

 
"priv

 
eacute;e

 
"

 
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)

 
;

 
    }

 
/

 
/

 
m

 
eacute;thode

 
priv

 
eacute;e

 
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)

 
;

 
    }

 
}

 

?





Puis , nous instantion quelques objets issue de ces classes , et nous réalisons des aggrégations et désaggrégations , tout en affichant quelques résultats :

Exemple 4 . test_aggregation.php

 
?php

 
include

 
"

 
storageclasses.inc"

 
;

 
/

 
/

 
quelques

 
utilitaires

 
function

 
p_arr($arr

 
)

 
{

 
foreach($arr

 
as

 
$k=

 
$v

 
)

 
$out[

 
]

 
=

 
"\t$k

 
=

 
$v"

 
;

 
return

 
implode("\n"

 
,

 
$out)

 
;

 
}

 
function

 
object_info($obj

 
)

 
{

 
$out[

 
]

 
=

 
"Classe

 
:

 
".get_class($obj)

 
;

 
foreach(get_object_vars($obj

 
)

 
as

 
$var=

 
$val

 
)

 
if

 
(is_array($val)

 
)

 
$out[

 
]

 
=

 
"propri

 
eacute;t

 
eacute

 
;

 
:

 
$var

 
(array)\n".p_arr($val)

 
;

 
        else

 
$out[

 
]

 
=

 
"propri

 
eacute;t

 
eacute

 
;

 
:

 
$var

 
=

 
$val"

 
;

 
foreach(get_class_methods($obj

 
)

 
as

 
$method

 
)

 
$out[

 
]

 
=

 
"m

 
eacute;thode

 
:

 
$method"

 
;

 
return

 
implode("\n"

 
,

 
$out)

 
;

 
}

 
$data

 
=

 
array(M_PI

 
,

 
"kludge

 
!=

 
cruft")

 
;

 
/

 
/

 
cr

 
eacute;ons

 
quelques

 
objets

 
simples

 
$fs

 
=

 
new

 
FileStorage($data)

 
;

 
$ws

 
=

 
new

 
WDDXStorage($data)

 
;

 
/

 
/

 
affichons

 
des

 
informations

 
sur

 
ces

 
objets

 
echo

 
"\$fs

 
object\n"

 
;

 
echo

 
object_info($fs)

 
."\n"

 
;

 
echo

 
"\n\$ws

 
object\n"

 
;

 
echo

 
object_info($ws)

 
."\n"

 
;

 
/

 
/

 
maintenant

 
,

 
quelques

 
aggr

 
eacute;gations

 
echo

 
"\nAggr

 
eacute;geons

 
\$fs

 
avec

 
la

 
classe

 
WDDXStorage\n"

 
;

 
aggregate($fs

 
,

 
"WDDXStorage")

 
;

 
echo

 
"L'objet

 
\$fs

 
\n"

 
;

 
echo

 
object_info($fs)

 
."\n"

 
;

 
echo

 
"\nAggr

 
eacute;geons

 
le

 
r

 
eacute;sultat

 
avec

 
la

 
classe

 
DBStorage

 
\n"

 
;

 
aggregate($fs

 
,

 
"DBStorage")

 
;

 
echo

 
"L'objet

 
\$fs

 
\n"

 
;

 
echo

 
object_info($fs)

 
."\n"

 
;

 
echo

 
"\nEt

 
finalement

 
,

 
d

 
eacute;saggr

 
eacute;geons

 
WDDXStorage\n"

 
;

 
deaggregate($fs

 
,

 
"WDDXStorage")

 
;

 
echo

 
"L'objet

 
\$fs

 
\n"

 
;

 
echo

 
object_info($fs)

 
."\n"

 
;

 

?





Etudions maintenant le résultat du script pour comprendre les effets secondaires et les limitations des aggrégations d ' objets en PHP . D' abord , nous avons créé $fs et $ws et ils fournissent le bon résultat (suivant la définition de leur classe ) . Notez que dans le but de l' aggrégation d'objets , les éléments privés d'une classe ou d'un objet doivent commencer par un souligné ("_" ) , même si il n 'y a pas de distinction réelle entre un objet privé et un objet public .

 
L'

 
objet

 
$fs

 
Classe

 
:

 
filestorage

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
data

 
(array

 
)

 
0

 
=

 
3.1415926535898

 
1

 
=

 
kludge

 
!=

 
cruft

 
m

 
eacute;thode

 
:

 
filestorage

 
m

 
eacute;thode

 
:

 
write

 
L'objet

 
$ws

 
Classe

 
:

 
wddxstorage

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
data

 
(array

 
)

 
0

 
=

 
3.1415926535898

 
1

 
=

 
kludge

 
!=

 
cruft

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
version

 
=

 
1.0

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
_id

 
=

 
ID::9bb2b640764d4370eb04808af8b076a5

 
m

 
eacute;thode

 
:

 
wddxstorage

 
m

 
eacute;thode

 
:

 
store

 
m

 
eacute

 
;thode

 
:

 
_genid





Nous aggrégeons alors $fs avec la classe WDDXStorage , et nous affichons les informations . Nous pouvons aussi vior que même si l' objet $fs est toujours du type FileStorage , il a maintenant la propriété $version , et la méthode store( ) , qui sont définies dans WDDXStorage . Une chose importante à noter est que les éléments privés n' ont pas été aggrégés , même si ils sont présents dans l 'objet $ws . Un autre absent est le constructeur de WDDXStorage , qu' il n'est pas logique d 'aggréger .

 
Aggr

 
eacute;

 
geons

 
\$fs

 
avec

 
la

 
classe

 
WDDXStorage

 
L'objet

 
$fs

 
Classe

 
:

 
filestorage

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
data

 
(array

 
)

 
0

 
=

 
3.1415926535898

 
1

 
=

 
kludge

 
!=

 
cruft

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
version

 
=

 
1.0

 
m

 
eacute;thode

 
:

 
filestorage

 
m

 
eacute;thode

 
:

 
write

 
m

 
eacute

 
;thode

 
:

 
store





Le processus d' aggrégation est cumulatif , ce qui fait que lorsque nous aggrégeons $fs avec la classe DBStorage , nous générons un objet qui peut utiliser n 'importe laquelle des méthodes de stockage de ces classes .

 
Aggr

 
eacute;

 
geons

 
le

 
r

 
eacute;sultat

 
avec

 
la

 
classe

 
DBStorage

 
L'objet

 
$fs

 
Classe

 
:

 
filestorage

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
data

 
(array

 
)

 
0

 
=

 
3.1415926535898

 
1

 
=

 
kludge

 
!=

 
cruft

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
version

 
=

 
1.0

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
dbtype

 
=

 
mysql

 
m

 
eacute;thode

 
:

 
filestorage

 
m

 
eacute;thode

 
:

 
write

 
m

 
eacute;thode

 
:

 
store

 
m

 
eacute

 
;thode

 
:

 
save





Finalement , de la même façon que nous avons aggrégés les méthodes et propriétés dynamiquement , nous pouvons aussi les désaggrégéer . Si vous désaggrégeons la classe WDDXStorage de l ' objet $fs , nous allons obtenir :

 
Et

 
finalement

 
,

 
d

 
eacute;

 
saggr

 
eacute;geons

 
WDDXStorage

 
L'objet

 
$fs

 
Classe

 
:

 
filestorage

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
data

 
(array

 
)

 
0

 
=

 
3.1415926535898

 
1

 
=

 
kludge

 
!=

 
cruft

 
propri

 
eacute;t

 
eacute

 
;

 
:

 
dbtype

 
=

 
mysql

 
m

 
eacute;thode

 
:

 
filestorage

 
m

 
eacute;thode

 
:

 
write

 
m

 
eacute

 
;thode

 
:

 
save





Un point que nous n' avons pas mentionnéé ci-dessus et que l'aggrégation ne va pas écraser les méthodes ou propriétés déjà existantes dans l 'objet principal . Par exemple , la classe FileStorage définit une propriété $data , et la classe WDDXStorage Par exemple , la classe FileStorage définit une propriété $data , et la classe WDDXStorage aussi . Mais cette dernière ne sera pas impliquée dans l ' aggrégation .

Table des matières
aggregate_info -- returns an associative array of the methods and properties from each class that has been aggregated to the object.
aggregate_methods_by_list -- Aggrège sélectivement les méthodes d'une classe grâce à une liste
aggregate_methods_by_regexp -- Aggrège sélectivement les méthodes d'une classe grâce à une expression régulière
aggregate_methods -- Aggrège dynamiquement les méthodes d'une classe à un objet
aggregate_properties_by_list -- selective dynamic class properties aggregation to an object
aggregate_properties_by_regexp -- selective class properties aggregation to an object using a regular expression
aggregate_properties -- Aggrège dynamiquement les propriétés d'une classe à un objet
aggregate -- Aggrège dynamiquemetn des classes et objets
aggregation_info -- Retourne un tableau associatif décrivant les classes aggrégées
deaggregate -- Desaggrège un objet