Précédent   Forum des professionnels en informatique > PHP > Langage > Syntaxe
Syntaxe Forum d'entraide sur la syntaxe de PHP et la POO. Avant de poster -> FAQ syntaxe, Cours d'initiation et cours de POO
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 09/11/2011, 14h09   #1
Membre confirmé
 
Développeur informatique
Inscription : décembre 2008
Messages : 344
Détails du profil
Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : décembre 2008
Messages : 344
Points : 292
Points : 292
Par défaut [POO] Définir une méthode en dehors de la déclaration de la class

Bonjour,

Voilà, j'ai des librairies contenant des class, et pour des raisons pratiques je voudrait ajouter des méthodes à une de ces class, mais sans toucher à ma librairie et en évitant de déclarer une class dérivée juste pour ça...

Existe t-il donc en PHP un moyen d'ajouter une méthode à une class sans toucher à la librairie qui contient la déclaration de class originale (directement dans le code de ma page donc) ?

En vous remerciant par avance...
comode est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 14h26   #2
Modérateur
 
Inscription : septembre 2010
Messages : 7 136
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 136
Points : 8 498
Points : 8 498
non tu peux pas
__________________
http://blog.stealth35.com/
stealth35 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 14h30   #3
Membre confirmé
 
Développeur informatique
Inscription : décembre 2008
Messages : 344
Détails du profil
Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : décembre 2008
Messages : 344
Points : 292
Points : 292
Bon bha comme ça, c'est clair !

merci !
comode est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 18h17   #4
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 991
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 991
Points : 5 032
Points : 5 032
En théorie non, c'est impossible contrairement à ce qu'on peut voir en JavaScript notamment.

En pratique il existe des patterns pour faire ça, dont le plus adapté à ce cas est le pattern Decorator.
Le principe est d'encapsuler un objet dans un autre qui va le "décorer", y ajouter de nouvelles fonctionnalités: http://en.wikipedia.org/wiki/Decorator_pattern

Je te recommande fortement l'usage de ce pattern.

S'il s'agit d'une spécialisation, un héritage est envisageable également. Attention à ne pas tomber dans les écueils de l'héritage fonctionnel comme expliqué par ici.
Citation:
L'héritage de classes est bien souvent mal employé par les développeurs qui lui donnent une signification plus large que nécessaire. L'héritage définit normalement une relation sémantique entre deux classes. Par exemple, un bouton est un composant graphique. Malheureusement, à cette relation sémantique est souvent substituée une relation fonctionnelle. On n'hérite plus alors d'une autre classe pour marquer des qualités intrinsèques mais pour hériter de fonctionnalités qui évitent au programmeur de devoir les implémenter à nouveau. En résumé, sous prétexte de favoriser la réutilisation du code, le développeur se rend coupable d'une grave erreur de conception qui peut avoir des conséquences assez importantes dans des API publiques.
D'autres solutions existent comme l'héritage parasitaire (je vais me faire avoiner la tête pour avoir dit ça mais ça existe) ou l'augmentation de classes.

Exemple d'une classe parfaitement générique en PHP:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
final class GenericObject {
 
  private $_data = array();
  private $_methods = array();
 
  public function __get ($key) {
    return isset($this->_data[$key]) ? $this->_data[$key] : null;
  }
 
  public function __set ($key, $value) {
    $this->_data[$key] = $value;
  }
 
  public function fn ($method, $alpha) {
    $this->_methods[$method] = $alpha;
  }
 
  public function __call ($method, $args) {
    if (isset($this->_methods[$method])) {
      array_unshift($args, $this);
      return call_user_func_array($this->_methods[$method], $args);
    }
    throw new BadMethodCallException('No such $method');
  }
}
 
$any = new GenericObject;
 
$any->fn('setName', create_function('$that,$name','$that->name = $name;'));
$any->fn('displayName', create_function('$that', 'echo $that->name;'));
 
$any->setName('Peter');
$any->displayName();
$any->setName('Joe');
$any->displayName();
Note: toutes les méthodes ajoutées grâce à GenericObject::fn doivent impérativement prendre un premier paramètre $that qui sert à faire passer la référence $this à l'intérieur de la fonction anonyme.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 18h22   #5
Modérateur
 
Inscription : septembre 2010
Messages : 7 136
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 136
Points : 8 498
Points : 8 498
sinon en marrant t'as

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Test
{
    public function __call($name, $arguments)
    {
        if ($this->$name instanceof \Closure) {
            return call_user_func_array($this->$name, $arguments);
        }
    }
}
 
$test = new Object();
 
$test->func = function($str) {
    return 'hello '.$str;
};
 
echo $test->func('world');
__________________
http://blog.stealth35.com/
stealth35 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 18h35   #6
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 991
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 991
Points : 5 032
Points : 5 032
Y'a ça aussi pour faire de la programmation orientée prototype sous PHP 5.3:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Obj
{
    public function __construct($methods=array())
    {
        $this->methods = $methods;
    }
 
    public function method($name)
    {
        if (!isset($this->methods[$name]))
        throw new BadMethodCallException();
 
        return $this->methods[$name];
    }
 
    public function fn($name, $fn)
    {
        $this->methods[$name] = $fn;
        return $this;
    }
 
    public function __call($name, $args)
    {
        return call_user_func_array(
        $this->method($name),
        array_merge(array($this), $args)
        );
    }
}
 
// Allow chaining method calls off the constructor..
function Obj($methods=array())
{
    return new Obj($methods);
}
https://gist.github.com/591139

Enfin, pour moi le décorateur y'a que ça de vrai
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 20h21   #7
Membre Expert
 
Avatar de Seb33300
 
Homme Sébastien Alfaiate
Développeur Web
Inscription : janvier 2007
Messages : 1 329
Détails du profil
Informations personnelles :
Nom : Homme Sébastien Alfaiate
Âge : 26
Localisation : France, Gironde (Aquitaine)

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Multimédia et Internet

Informations forums :
Inscription : janvier 2007
Messages : 1 329
Points : 1 657
Points : 1 657
Et pourquoi ne pas tout simplement créer une autre classe qui hérite de celle que tu veux modifier ?
__________________
Zend Certified Engineer PHP 5.3

« Crois-tu comprendre le monde juste en matant le 20H Ou connaître l'histoire en ayant lu que l'angle des vainqueurs ? » Keny Arkana
Seb33300 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/11/2011, 20h45   #8
Membre confirmé
 
Développeur informatique
Inscription : décembre 2008
Messages : 344
Détails du profil
Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : décembre 2008
Messages : 344
Points : 292
Points : 292
Ummmummmm... A vrai dire, en posant la question, je m'attendais à une réponse du type "marrant" pour reprendre les propos de stealth35...

L'idée était justement d'éviter de faire une spécialisation en créant une class dérivée qui n'a (philosophiquement) pas lieu d'exister, tout en évitant de rajouter une méthode à ma class sans modifier (et alourdir) la librairie...

Si je comprend bien Benjamin, ta solution avec un design pattern impose tout de même de modifier la librairie pour rendre la class apte à accueillir de nouvelles méthodes !? Par ailleurs, la déclaration de nouvelles méthodes peut rapidement poser un problème de lisibilité non ?

Suite à la 1er réponse que l'on m'a donné, j'avais finalement opté pour faire une class spécialisée, mais comme je ne suis pas content de ma solution, je la ré-écrirais bien façon "marrante" : $ojb->my_func = function(...){...}

Y'a t-il une raison ou des contres indications qui devraient me pousser à éviter cette méthode pourtant fort simple ?

en attendant, merci pour ces réponses très instructivent !

EDIT :

Citation:
Et pourquoi ne pas tout simplement créer une autre classe qui hérite de celle que tu veux modifier ?
Parce que c'est conceptuellement faux en POO... C'est un peu comme utiliser des class virtuelle pures... C'est pas indispensable, on peut faire autrement, mais au final, si on ne respecte pas la philosophie OO et qu'on ne les utilise pas, un jour ou l'autre, on le regrette...
comode est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/11/2011, 10h27   #9
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 991
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 991
Points : 5 032
Points : 5 032
Citation:
Envoyé par Seb33300 Voir le message
Et pourquoi ne pas tout simplement créer une autre classe qui hérite de celle que tu veux modifier ?
Parce que c'est conceptuellement faux en POO... C'est un peu comme utiliser des class virtuelle pures... C'est pas indispensable, on peut faire autrement, mais au final, si on ne respecte pas la philosophie OO et qu'on ne les utilise pas, un jour ou l'autre, on le regrette...
ça n'a pas grand chose à voir avec les interfaces, on parle ici d'héritage contionnel ce qui est hautement dangereux et déconseillé. Un héritage est caractérisé par la relation "est un espèce de" et rien d'autre !

Citation:
L'idée était justement d'éviter de faire une spécialisation en créant une class dérivée qui n'a (philosophiquement) pas lieu d'exister, tout en évitant de rajouter une méthode à ma class sans modifier (et alourdir) la librairie...
Tout à fait

Citation:
Si je comprend bien Benjamin, ta solution avec un design pattern impose tout de même de modifier la librairie pour rendre la class apte à accueillir de nouvelles méthodes !? Par ailleurs, la déclaration de nouvelles méthodes peut rapidement poser un problème de lisibilité non ?
Non pas vraiment. Il s'agit de créer un wrappeur en fait (embalage en anglais) pour ajouter de nouvelles fonctionnalités à une instance (le faire au niveau de la classe est impossible sauf si la classe est définie pour recevoir des augmentations comme mentionné plus haut). Dans tous les cas on ne touche pas à la classe d'origine.

Citation:
Y'a t-il une raison ou des contres indications qui devraient me pousser à éviter cette méthode pourtant fort simple ?
C'est pas super propre voilà tout. Ces méthodes d'augmentations caractérisent en quelque sorte une façon de faire de programmation orienté prototype, ce qui est très adapté à des langages dynamiques (comme JavaScript pour ne citer que lui) mais beaucoup moins à des langages comme PHP qui n'ont pas du tout étés prévus pour ça au départ.

Je reste sur ma recommandation concernant le pattern Decorator.

Note: si ton but est de simplifier l'usage d'une classe tu peux utiliser le pattern Façade: http://fr.wikipedia.org/wiki/Fa%C3%A..._conception%29
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 10h33.


 
 
 
 
Partenaires

Hébergement Web