8797 sujets

Développement web côté serveur, CMS

Bonjour à tous,

je souhaiterais savoir s'il est possible en PHP5 de créer une interface dont pourrait hériter d'autres classes. Le problème étant que concrètement, dans ce cas, je ne vois pas comment est spécifié l'implémentation de l'interface au moment de l'instantiation d'une des classes héritantes. suis-je complètement à côté de la plaque ?

l'idée étant d'avoir une série d'objet héritant tous d'une classe de base, cette classe de base pouvant être "switchée" en fonction par exemple du type de base de données qu'elle utilise.

merci à ceux qui pourront m'éclairer de leur grande sagesse...
Bonjour,

je ne suis pas certain d'avoir compris ce que tu veux faire, mais les notions d'interface et d'héritage (ainsi que d'autres comme les classes abstraites) existent effectivement en php5.

Il est possible d'implémenter plusieurs interfaces par contre l'héritage multiple est interdit. La syntaxe à utiliser lors de la déclaration est la suivante
class my_class [extends parent_class] [implements interface_1[, interface_2[, interface...]]] {
   // code php...
}



Plus d'info (manuel php @php.net):
Interfaces en php5
Syntaxe de base des classes (et héritage)
Modifié par Necromantik (01 Dec 2007 - 18:38)
Necromantik a écrit :
Bonjour,

je ne suis pas certain d'avoir compris ce que tu veux faire, mais les notions d'interface et d'héritage (ainsi que d'autres comme les classes abstraites) existent effectivement en php5.

Il est possible d'implémenter plusieurs interfaces par contre l'héritage multiple est interdit. La syntaxe à utiliser lors de la déclaration est la suivante
class my_class [extends parent_class] [implements interface_1[, interface_2[, interface...]]] {
   // code php...
}



Merci, c'est effectivement ce que j'aurai du faire pour illustrer ma question : donner un bout de code Smiley smile . il s'agit d'implémenter une classe qui soit à la fois une interface et une classe de base dont hérite d'autre classe :


interface Random{
   // définie un comportement type
  getRandom();
}

class myRandom extends Random{
  // étend le comportement de parent_class dans le cas d'un objet particulier
 getBinaryRandom(){round(parent::getRandom())};
}


la classe myRandom peut appeler aussi bien getRandom que getBinaryRandom ; elle est indépendente de la façon dont est implémentée getRandom.

il s'agit enfin d'implémenter l'interface de sorte à étendre son comportement aux classes héritantes... et là je ne vois pas comment faire...


class PHPRandom implements Random {
  getRandom(){ return randomize() }
}


comment la classe myRandom sait-elle concrétement qu'elle doit utiliser cette implémentation PHPRandom ?

Merci pour les liens, je vais jeter un coup d'oeil...
Modifié par lex (02 Dec 2007 - 08:57)
Je me rend compte que l'utilisation que je fais de l'interface pour répondre à mon problême n'est peut être pas très correcte. Donc je vais essayer d'exposer ce que je cherche à faire :

j'ai une classe mère digitalObject dont l'implémentation peut varier en fonction par exemple du type de base de données utilisée.

plusieurs classes hérite de cette classe mère pour caractériser différents types d'objets : dObject1, dObject2, etc ;

au moment de l'instanciation de l'un de ces objets : myObject = new dObject1, je souhaite pouvoir spécifier l'implémentation de la classe digitalObject utilisé. Par exemple SQLObject. C'set un peu le principe d'une factory, sauf que je tiens à ce que chacun des objets enfants puisse être utilisé avec les méthodes de la classe mère.

Voilà, j'espère que c'est plus clair. Smiley smile
lex a écrit :
Je me rend compte que l'utilisation que je fais de l'interface pour répondre à mon problême n'est peut être pas très correcte.

En effet, les interfaces ne sont que des calques à suivre et n'ont en fait qu'une fonction de "contrôle qualité" il ne peuvent pas implémenter de méthodes.

lex a écrit :
j'ai une classe mère digitalObject [...]

Je ne crois pas qu'il soit possible de définir dynamiquement le nom de la class étendue et donc de faire ce que tu veux (si j'ai bien compris).
Ceci-dit, il est toujours possible de générer le code puis d'utiliser eval() mais c'est pas forcement une bonne solution.
Une autre façon de faire est d'instancier la classe "parent" comme une variable interne de la classe "enfant" mais cela pose problème pour l'accès aux méthodes.
Necromantik a écrit :

Ceci-dit, il est toujours possible de générer le code puis d'utiliser eval() mais c'est pas forcement une bonne solution.

non, en effet Smiley smile

Necromantik a écrit :

Une autre façon de faire est d'instancier la classe "parent" comme une variable interne de la classe "enfant" mais cela pose problème pour l'accès aux méthodes.

je m'étais rabattu sur cette alternative, mais c'est très lourd : il faut reecrire toutes les fonctions pour les classes enfants - impossible à gérer (en fait, j'avais un objet abstract intermédiaire qui m'évitait de le faire pour tous les enfants, mais de toute façon, ça n'était pas élégant...).

merci pour le coup de main.
Modifié par lex (03 Dec 2007 - 11:47)
lex a écrit :
Je me rend compte que l'utilisation que je fais de l'interface pour répondre à mon problême n'est peut être pas très correcte. Donc je vais essayer d'exposer ce que je cherche à faire :

j'ai une classe mère digitalObject dont l'implémentation peut varier en fonction par exemple du type de base de données utilisée.

plusieurs classes hérite de cette classe mère pour caractériser différents types d'objets : dObject1, dObject2, etc ;

au moment de l'instanciation de l'un de ces objets : myObject = new dObject1, je souhaite pouvoir spécifier l'implémentation de la classe digitalObject utilisé. Par exemple SQLObject. C'set un peu le principe d'une factory, sauf que je tiens à ce que chacun des objets enfants puisse être utilisé avec les méthodes de la classe mère.

Voilà, j'espère que c'est plus clair. Smiley smile

Pas sûr d'avoir bien pigé, mais je pense que c'est le design pattern "bridge" qu'il te faut (permet de pouvoir faire varier l'abstraction et l'implémentation de manière indépendante). Cela peut se faire facilement en php grâce à l'agrégation.


abstract class ObjectBase { // ou une interface
  public function do()...
  public function make()...
}
class SQLObject extends ObjectBase { .. }

class BlahObject extends ObjectBase { .. }

abstract class digitalObject {
  
  private $implementation;
  
  public function __construct(ObjectBase $implementation) {
    $this->implementation = $implementation;
  }
  
  public function blah() {
    $this->implementation->do(); // le bridge
  }
}

class MyObject extends digitalObject {
  //.. redéfinir le constructeur si besoins.
  //.. caller parent::__construct($implementation)
}

$myObject = new MyObject(new SQLObject);
$myObject->blah();