Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

j'apprends php (3)

14 réponses
Avatar
Olivier Masson
Bonjour,

Je souhaitais modifier un projet qui ne m'appartient pas.
Mais dès le départ, quelque chose dont la logique m'échappe. Je veux
créer une classe dérivée. Or, c'est cette classe dérivée qu'il faudra
/instancier/.

Mais cette classe que je veux dériver l'a déjà été par d'autres pour
ajouter des fonctionnalités.
Chacun donne son petit nom et on se retrouve avec autant de nomq qu'il
existe de fonctionnalités supplémentaires.
class diet extends original
class crystal extends original
class sans-cafeine extends original

Donc, comment s'organise-t-on pour ajouter toutes les fonctionnalités
que l'on souhaite (une class diet + crystal + sans-cafeine) ?

Merci.

10 réponses

1 2
Avatar
Jean-Francois Ortolo
Le 30/03/2010 22:43, Olivier Masson a écrit :
Bonjour,

Je souhaitais modifier un projet qui ne m'appartient pas.
Mais dès le départ, quelque chose dont la logique m'échappe. Je veux
créer une classe dérivée. Or, c'est cette classe dérivée qu'il faudra
/instancier/.

Mais cette classe que je veux dériver l'a déjà été par d'autres pour
ajouter des fonctionnalités.
Chacun donne son petit nom et on se retrouve avec autant de nomq qu'il
existe de fonctionnalités supplémentaires.
class diet extends original
class crystal extends original
class sans-cafeine extends original

Donc, comment s'organise-t-on pour ajouter toutes les fonctionnalités
que l'on souhaite (une class diet + crystal + sans-cafeine) ?

Merci.




Bonjour Monsieur

En C++, c'est l'héritage mutiple qui permet celà, je crois...

En fait, je confond un peu la notion d'interface en Java, avec la
notion d'héritage ( je n'ai plus lu un bouqin sur javase depuis très
longtemps, même chose en C++, et je ne sais même pas si le concept
d'interface existe en C++, et je ne suis pas très ferré en poo ).

Nonobstant la possibilité de simplement recopier le code des
différentes classes en question, n'y aurait-il pas risque, en cas
d'héritage multiple à partir de plusieurs classes dérivées d'une classe,
de collision entre objets instanciés de la classe résultante, qui
seraient le résultat de chacune des classes héritées, donc risque de
collision si les fonctionnalités se recouvrent, ou si ces classes
héritées, utilisent de manière différente des méthodes ou des variables
héritées de la classe racine ?

En d'autres termes, est-il envisageable en poo, de concevoir un
héritage multiple à partir de plusieurs classes, si deux au moins des
classes ancêtres, héritent d'une classe unique ?

Bien à vous.

Amicalement.

Jean-François Ortolo

--
Visitez le site http://www.pronostics-courses.fr/
donnant des Statistiques, Pronostics et Historiques graphiques
très élaborés.

Les Statistiques sont calculées d'après une base de données
allant du 1er Janvier 2000 jusqu'à très récemment.
Avatar
Pascal
Olivier Masson a écrit :
Bonjour,



Bonjour,

Je souhaitais modifier un projet qui ne m'appartient pas.



Bon courage ! ;-)

Mais dès le départ, quelque chose dont la logique m'échappe. Je veux
créer une classe dérivée. Or, c'est cette classe dérivée qu'il faudra
/instancier/.



Pas de problème a priori.

Mais cette classe que je veux dériver l'a déjà été par d'autres pour
ajouter des fonctionnalités.
Chacun donne son petit nom et on se retrouve avec autant de nomq qu'il
existe de fonctionnalités supplémentaires.
class diet extends original
class crystal extends original
class sans-cafeine extends original



Ok, donc plusieurs classes filles héritant de la même classe parent.
Que du classique jusque-là.

Donc, comment s'organise-t-on pour ajouter toutes les fonctionnalités
que l'on souhaite (une class diet + crystal + sans-cafeine) ?



Ah oui, c'est là que ça coince.
Pas d'héritage multiple avec PHP, donc pas de possibilité d'écrire une
définition de classe genre :
class Total extends Diet, Crystal, Sans_cafeine {...}

La seule solution, je crois, est de redéfinir une classe héritant de la
classe de base (Original) et reprenant les propriétés et méthodes
intéressantes des classes étendues.

Il y en a d'autres nettement plus tordues que je déconseille, du type :
http://fr2.php.net/manual/fr/language.oop5.basic.php#88249

Merci.



De rien.
Cordialement,
Pascal
Avatar
Bruno Desthuilliers
Olivier Masson a écrit :
Bonjour,

Je souhaitais modifier un projet qui ne m'appartient pas.
Mais dès le départ, quelque chose dont la logique m'échappe. Je veux
créer une classe dérivée. Or, c'est cette classe dérivée qu'il faudra
/instancier/.

Mais cette classe que je veux dériver l'a déjà été par d'autres pour
ajouter des fonctionnalités.
Chacun donne son petit nom et on se retrouve avec autant de nomq qu'il
existe de fonctionnalités supplémentaires.



Problème de conception assez courant hélas consistant à abuser de
l'héritage au lieu de réfléchir. Après, sans connaître le contexte, pas
moyen de dire quelle serait la bonne solution, mais à vue de nez on
pourrait penser aux patterns "décorateur" et "stratégie".

class diet extends original
class crystal extends original
class sans-cafeine extends original

Donc, comment s'organise-t-on pour ajouter toutes les fonctionnalités
que l'on souhaite (une class diet + crystal + sans-cafeine) ?



Cf ci-dessus. Encore une fois, sans connaître le contexte, ça relève un
peu de la boule de cristal, mais je pense qu'un refactoring basé sur les
deux patterns ci-dessus pourrait être un bon point de départ.

Mes deux centimes...
Avatar
Bruno Desthuilliers
Pascal a écrit :
Olivier Masson a écrit :


(snip)
Ok, donc plusieurs classes filles héritant de la même classe parent.
Que du classique jusque-là.



Hélas oui - une erreur classique... Qui se perpétuera tant que la
littérature introductive à l'OO présentera l'héritage comme une
fonctionnalité essentielle, de préférence à travers des examples ineptes.

L'héritage, c'est comme les regexps - un super outil quand on l'utilise
à bon escient...

Donc, comment s'organise-t-on pour ajouter toutes les fonctionnalités
que l'on souhaite (une class diet + crystal + sans-cafeine) ?



Ah oui, c'est là que ça coince.
Pas d'héritage multiple avec PHP, donc pas de possibilité d'écrire une
définition de classe genre :
class Total extends Diet, Crystal, Sans_cafeine {...}



Le problème n'est pas tant lié à l'absence d'héritage multiple qu'à
l'utilisation manifestement inappropriée de l'héritage en premier lieu.

La seule solution, je crois, est de redéfinir une classe héritant de la
classe de base (Original) et reprenant les propriétés et méthodes
intéressantes des classes étendues.



En les copiants/collant ???

Il y en a d'autres nettement plus tordues que je déconseille, du type :
http://fr2.php.net/manual/fr/language.oop5.basic.php#88249



Tordue en effet, mais ça donne au moins un point de départ pour une
implémentation d'un support générique de la composition/délégation en PHP.
Avatar
Olivier Masson
Le 31/03/2010 13:28, Bruno Desthuilliers a écrit :

Problème de conception assez courant hélas consistant à abuser de
l'héritage au lieu de réfléchir. Après, sans connaître le contexte, pas
moyen de dire quelle serait la bonne solution, mais à vue de nez on
pourrait penser aux patterns "décorateur" et "stratégie".



Bien entendu, j'ignore ce que sont ces patterns.
Mais, plus généralement (la classe que j'utilise est très simple : il
s'agit de fpdf dont j'ai parlé dans un autre fil), si on souhaite
modifier une classe très connue, utilisée, mise à jour régulièrement,
c'est uniquement par héritage qu'on peut ajouter des fonctions non ?
Avatar
Olivier Masson
Le 31/03/2010 13:28, Pascal a écrit :

Ah oui, c'est là que ça coince.
Pas d'héritage multiple avec PHP, donc pas de possibilité d'écrire une
définition de classe genre :
class Total extends Diet, Crystal, Sans_cafeine {...}




Ok, donc ça existe. Le contraire me semblait étrange.

Après, me débrouiller avec ce que j'ai, c'est simple. Mais j'aurais
voulu faire plus conventionnel pour apprendre. PHP5 ne le permettant
pas, on va faire du copier/coller.

Merci.
Avatar
Mickael Wolff
Bruno Desthuilliers a écrit :

Tordue en effet, mais ça donne au moins un point de départ pour une
implémentation d'un support générique de la composition/délégation en PHP.



Sauf que le code est faux, pas assez générique en fait. Dès qu'il y
aura des propriétés privées ans les ancetres ou les descendant, ça
pétera. J'ai essayé dans mon Framework, j'ai eu des problèmes :p

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Mickael Wolff
Olivier Masson a écrit :

Mais cette classe que je veux dériver l'a déjà été par d'autres pour
ajouter des fonctionnalités.
Chacun donne son petit nom et on se retrouve avec autant de nomq qu'il
existe de fonctionnalités supplémentaires.
class diet extends original
class crystal extends original
class sans-cafeine extends original

Donc, comment s'organise-t-on pour ajouter toutes les fonctionnalités
que l'on souhaite (une class diet + crystal + sans-cafeine) ?



Comme l'a dit Bruno, quelque chose inspiré du pattern decorator. Mais
dans ton cas, je pense qu'il faudrait récrire la hiérarchie avec un
système plus intelligent. Qui s'inspirerait du pattern composition
(composite). Mais c'est beaucoup de boulot, le copier-coller soit avec
toi si tu n'as pas le temps.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Bruno Desthuilliers
Mickael Wolff a écrit :

Sauf que le code est faux,



C'est possible en effet - honnêtement, je n'ai fait que survoler
l'exemple :-/
Avatar
Bruno Desthuilliers
Olivier Masson a écrit :
Le 31/03/2010 13:28, Bruno Desthuilliers a écrit :

Problème de conception assez courant hélas consistant à abuser de
l'héritage au lieu de réfléchir. Après, sans connaître le contexte, pas
moyen de dire quelle serait la bonne solution, mais à vue de nez on
pourrait penser aux patterns "décorateur" et "stratégie".



Bien entendu, j'ignore ce que sont ces patterns.



C'est relativement documenté sur le net.

Le pattern stratégie consiste à déléguer une partie déterminée du
comportement à un autre objet (ou à une fonction de rappel pour ce que
ça vaut), généralement spécifié(e) à l'instanciation. Ca permet de
"plugger" des comportements différents sans devoir toucher à la classe
de base ou créer une nouvelle sous-classe.

Le pattern décorateur consiste à ajouter/adapter les fonctionnalités
d'un objet en le décorant dans un autre objet (compatible du point de
vue de l'API of course), le quel délèguera une partie du travail à
l'objet d'origine.

Dans les deux cas, on se base sur un principe de composition /
délégation, dont l'héritage n'est finalement qu'une forme statique et
fortement couplée. L'avantage par rapport à l'héritage réside dans le
découplage et l'aspect dynamique.

Ces deux techniques, utilisées séparément ou conjointement permettent de
varier/adapter les comportements sans avoir de problème d'explosion
combinatoire des sous-classes - le problème que tu rencontres actuellement.

Mais, plus généralement (la classe que j'utilise est très simple : il
s'agit de fpdf dont j'ai parlé dans un autre fil), si on souhaite
modifier une classe très connue, utilisée, mise à jour régulièrement,
c'est uniquement par héritage qu'on peut ajouter des fonctions non ?



Encore une fois : l'héritage (dans le sens "héritage d'implémentation")
est extrêment survalorisé et surestimé dans la majorité de la
littérature introductive à l'OO. En pratique, dans un langage à typage
dynamique (ou à inférence de type), l'héritage d'implémentation n'est
qu'une forme statique et très fortement couplée de composition / délégation.

Si tu veux juste AJOUTER des fonctionnalités, le pattern décorateur est
une autre solution, dont la raison d'être est précisément d'éviter
l'explosion combinatoire des sous-classes - puisqu'un décorateur
acceptera aussi bien de décorer l'objet "de base" qu'un *autre*
décorateur, ce qui permet de "composer" dynamiquement un objet de base
et X décorateurs.

Pour reprendre ton example, "diet", "crystal" et "sans-cafeine" seraient
des décorateurs pour "original", et pour avoir la combinaison des trois,
tu les compose juste dans l'ordre qui te convient, ie:

$bidule = new DecorateurDiet(
new DecorateurCrystal(
new DecorateurSansCafeine(
new Original()
)
)
);


HTH
1 2