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
.
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
.
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
.
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
:
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
.