mirror of
https://github.com/macintoshplus/doc-fr.git
synced 2026-03-26 09:52:17 +01:00
git-svn-id: https://svn.php.net/repository/phpdoc/fr/trunk@261459 c90b9560-bf6c-de11-be94-00142212c4b1
458 lines
12 KiB
XML
458 lines
12 KiB
XML
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!-- $Revision: 1.2 $ -->
|
|
<!-- EN-Revision: 1.3 Maintainer: yannick Status: ready -->
|
|
<!-- Reviewed: yes -->
|
|
|
|
<appendix xml:id="objaggregation.examples">
|
|
&reftitle.examples;
|
|
<section xml:id="objaggregation.examples.association">
|
|
<title>Exemples d'agrégation d'objets</title>
|
|
<para>
|
|
Une <emphasis>Association</emphasis> 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 :
|
|
<example>
|
|
<title>Association de classes</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class MyDateTime {
|
|
|
|
function MyDateTime()
|
|
{
|
|
// constructeur vide
|
|
}
|
|
|
|
function now()
|
|
{
|
|
return date("Y-m-d H:i:s");
|
|
}
|
|
}
|
|
|
|
class Report {
|
|
var $_dt;
|
|
// autres propriétés ...
|
|
|
|
function Report()
|
|
{
|
|
$this->_dt = new MyDateTime();
|
|
// initialisation du code ...
|
|
}
|
|
|
|
function generateReport()
|
|
{
|
|
$dateTime = $this->_dt->now();
|
|
// autre code ...
|
|
}
|
|
|
|
// autres méthodes ...
|
|
}
|
|
|
|
$rep = new Report();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
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 :
|
|
<example>
|
|
<title>Association d'objets</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class MyDateTime {
|
|
// identique au précédent exemple
|
|
}
|
|
|
|
class MyDateTimePlus {
|
|
var $_format;
|
|
|
|
function MyDateTimePlus($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éférence à DateTime ici
|
|
// autre propriété ...
|
|
|
|
function Report()
|
|
{
|
|
// initialisation
|
|
}
|
|
|
|
function setMyDateTime(&$dt)
|
|
{
|
|
$this->_dt =& $dt;
|
|
}
|
|
|
|
function generateReport()
|
|
{
|
|
$dateTime = $this->_dt->now();
|
|
// autre code ...
|
|
}
|
|
|
|
// autres méthodes ...
|
|
}
|
|
|
|
$rep = new Report();
|
|
$dt = new MyDateTime();
|
|
$dtp = new MyDateTimePlus("l, F j, Y (h:i:s a, T)");
|
|
|
|
// Génération du rapport avec une simple date
|
|
$rep->setMyDateTime(&$dt);
|
|
echo $rep->generateReport();
|
|
|
|
// plus loin dans le code ...
|
|
|
|
// Génération du rapport avec une date designée
|
|
$rep->setMyDateTime(&$dtp);
|
|
$output = $rep->generateReport();
|
|
// sauvegarde pour affichage dans la base
|
|
// ... etc ...
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
L'<emphasis>agrégation</emphasis>, d'un autre coté, implique
|
|
l'encapsulation et le masquage des parties de la combinaison. Nous
|
|
pouvons agré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 agrégée n'est pas accessible,
|
|
sauf via les méthodes de la classe contenant. L'agrégation d'instances
|
|
(agré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).
|
|
</para>
|
|
<para>
|
|
L'agrégation d'objets est une méthode naturelle pour représenter des
|
|
relations de type tout-partie (par exemple, une molécule est une agré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 agré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 agrégé.
|
|
</para>
|
|
</section>
|
|
<section xml:id="objaggregation.examples2">
|
|
&reftitle.examples;
|
|
<para>
|
|
Nous définissons trois classes, qui implémentent chacune une méthode de stockage
|
|
différente :
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>storage_classes.inc</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?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é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éthode privé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);
|
|
}
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Puis, nous "instantions" quelques objets issus de ces classes, et nous
|
|
réalisons des agrégations et désagrégations, tout en affichant
|
|
quelques résultats :
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>test_aggregation.php</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?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été : $var (array)\n" . p_arr($val);
|
|
} else {
|
|
$out[] = "propriété : $var = $val";
|
|
}
|
|
}
|
|
foreach (get_class_methods($obj) as $method) {
|
|
$out[] = "méthode : $method";
|
|
}
|
|
return implode("\n", $out);
|
|
}
|
|
|
|
|
|
$data = array(M_PI, "kludge != cruft");
|
|
|
|
// cré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 agrégations
|
|
|
|
echo "\nagrégeons \$fs avec la classe WDDXStorage\n";
|
|
aggregate($fs, "WDDXStorage");
|
|
echo "L'objet \$fs \n";
|
|
echo object_info($fs) . "\n";
|
|
|
|
echo"\nagrégeons le résultat avec la classe DBStorage \n";
|
|
aggregate($fs, "DBStorage");
|
|
echo "L'objet \$fs \n";
|
|
echo object_info($fs)."\n";
|
|
|
|
echo "\nEt finalement, désagrégeons WDDXStorage\n";
|
|
deaggregate($fs, "WDDXStorage");
|
|
echo "L'objet \$fs \n";
|
|
echo object_info($fs) . "\n";
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Etudions maintenant le résultat du script pour comprendre les effets
|
|
secondaires et les limitations des agrégations d'objets en PHP.
|
|
D'abord, nous avons créé <varname>$fs</varname> et <varname>$ws</varname>
|
|
et ils fournissent le bon résultat (suivant la définition de leur classe).
|
|
Notez que dans le but de l'agrégation d'objets,
|
|
<emphasis>les éléments privés d'une classe ou
|
|
d'un objet doivent commencer par un souligné ("_")</emphasis>,
|
|
même s'il n'y a pas de distinction réelle entre un objet
|
|
privé et un objet public.
|
|
</para>
|
|
<para>
|
|
<informalexample>
|
|
<programlisting>
|
|
<![CDATA[
|
|
$fs object
|
|
Classe : filestorage
|
|
propriété : data (array)
|
|
0 => 3.1415926535898
|
|
1 => kludge != cruft
|
|
méthode : filestorage
|
|
méthode : write
|
|
|
|
$ws object
|
|
Classe : wddxstorage
|
|
propriété : data (array)
|
|
0 => 3.1415926535898
|
|
1 => kludge != cruft
|
|
propriété : version = 1.0
|
|
propriété: _id = ID::9bb2b640764d4370eb04808af8b076a5
|
|
méthode : wddxstorage
|
|
méthode : store
|
|
méthode : _genid
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Nous agrégeons alors <varname>$fs</varname> avec la classe
|
|
<classname>WDDXStorage</classname>, et nous affichons les informations.
|
|
Nous pouvons aussi voir que même si l'objet <varname>$fs</varname>
|
|
est toujours du type <classname>FileStorage</classname>, il a maintenant
|
|
la propriété <varname>$version</varname>, et la méthode
|
|
<function>store</function>, qui sont définies dans
|
|
<classname>WDDXStorage</classname>. Une chose importante à noter est
|
|
que les éléments privés n'ont pas été
|
|
agrégés, même s'ils sont présents dans l'objet
|
|
<varname>$ws</varname>. Un autre absent est le constructeur de
|
|
<classname>WDDXStorage</classname>, qu'il n'est pas logique d'agréger.
|
|
</para>
|
|
<para>
|
|
<informalexample>
|
|
<programlisting>
|
|
<![CDATA[
|
|
agrégeons \$fs avec la classe WDDXStorage
|
|
L'objet $fs
|
|
Classe : filestorage
|
|
propriété : data (array)
|
|
0 => 3.1415926535898
|
|
1 => kludge != cruft
|
|
propriété : version = 1.0
|
|
méthode : filestorage
|
|
méthode : write
|
|
méthode : store
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Le processus d'agrégation est cumulatif, ce qui fait que
|
|
lorsque nous agrégeons <varname>$fs</varname> avec la classe
|
|
<classname>DBStorage</classname>, nous générons un objet qui
|
|
peut utiliser n'importe laquelle des méthodes de stockage de
|
|
ces classes.
|
|
</para>
|
|
<para>
|
|
<informalexample>
|
|
<programlisting>
|
|
<![CDATA[
|
|
agrégeons le résultat avec la classe DBStorage
|
|
L'objet $fs
|
|
Classe : filestorage
|
|
propriété : data (array)
|
|
0 => 3.1415926535898
|
|
1 => kludge != cruft
|
|
propriété : version = 1.0
|
|
propriété : dbtype = mysql
|
|
méthode : filestorage
|
|
méthode : write
|
|
méthode : store
|
|
méthode : save
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Finalement, de la même façon que nous avons agrégé
|
|
les méthodes et propriétés dynamiquement, nous pouvons aussi
|
|
les désagréger. Si nous désagrégeons
|
|
la classe <classname>WDDXStorage</classname> de l'objet <varname>$fs</varname>,
|
|
nous allons obtenir :
|
|
</para>
|
|
<para>
|
|
<informalexample>
|
|
<programlisting>
|
|
<![CDATA[
|
|
Et finalement, désagrégeons WDDXStorage
|
|
L'objet $fs
|
|
Classe : filestorage
|
|
propriété : data (array)
|
|
0 => 3.1415926535898
|
|
1 => kludge != cruft
|
|
propriété : dbtype = mysql
|
|
méthode : filestorage
|
|
méthode : write
|
|
méthode : save
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Un point que nous n'avons pas mentionné ci-dessus et que l'agrégation ne va
|
|
pas écraser les méthodes ou propriétés déjà existantes dans l'objet principal.
|
|
Par exemple, la classe <classname>FileStorage</classname> définit une
|
|
propriété <varname>$data</varname>, et la classe
|
|
<classname>WDDXStorage</classname> aussi. Mais cette dernière ne sera pas
|
|
impliquée dans l'agrégation.
|
|
</para>
|
|
</section>
|
|
</appendix>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"../../../manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|
|
|