IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Héritage, Interfaces et Type Hinting


Sujet :

Langage PHP

  1. #1
    Membre habitué Avatar de alejandro
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2004
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2004
    Messages : 167
    Points : 188
    Points
    188
    Par défaut Héritage, Interfaces et Type Hinting
    Bonjour,

    Je rencontre un comportement bizarre lors de l'interprétation de mon script php. Dans une classe Front_Dispatcher, j'ai un constructeur et une méthode qui sont censées recevoir chacune un argument de type Front_Router.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Front_Dispatcher
    extends Abstract_Strategy
    implements Interface_Observer
    {
        public function __construct( Front_Router $router )
        {
            $router->attach( $this );
            parent::__construct( $router );
        }
     
        public function update( Front_Router $observable )
        {
            print "updating std_dispatcher";
        }
    }
    Seulement je rencontre un problème avec l'une de ces deux méthodes :

    Fatal error: Declaration of Front_Dispatcher::update() must be compatible with that of Interface_Observer::update() in C:\Documents and Settings\alejandro\Mes documents\WebApps\www\system\Front\Dispatcher.php on line 5
    L'interface Interface_Observer déclare la méthode update suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public function update( Interface_Observable $observable );
    Donc je me dis que même si Front_Router implémente Interface_Observable via son parent Abstract_Observable, cela ne fonctionne pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Front_Router
    extends Abstract_Observable
    implements Interface_Strategy
    {
        public function execute()
        {
            $this->notify();
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    abstract class Abstract_Observable
    implements Interface_Observable
    Sauf que ...

    En ce qui concerne ma fonction __construct, qui requiert également un objet de type Front_Router, je n'ai pas de message d'erreur, alors que je demande un argument de type Interface_Strategy dans son parent Abstract_Strategy :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    abstract class Abstract_Strategy
    implements Interface_Strategy
    {
        protected $_strategy;
     
        public function __construct( Interface_Strategy $strategy )
        {
            $this->_strategy = $strategy;
        }
     
        public function execute()
        {
            $this->_strategy->execute();
        }
    }
    Sauf que, différence avec update, là je l'implémente directement dans le Front_Router mon Interface_Strategy, ce qui fait qu'il a l'air de me le prendre.

    Donc ma question est la suivante : Pourquoi ça marche dans un sens et pas dans l'autre ? Est-ce une insuffisance de PHP ou un défaut de conception venant de ma part ?

    Sachant également que si je modifie ma fonction update dans Front_Router comme suit mon problème est réglé et tout fonctionne correctement :

    public function update( Interface_Observable $observable )
    Simplement je voudrais contraindre mon argument à être de type Front_Router ou d'une classe qui en hériterais, afin de pouvoir utiliser certaines méthodes spécifiques à tous les Front_Routers mais pas forcément à un objet implémentant Interface_Observable.

    Votre avis ?

  2. #2
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    il faudrait mettre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public function update(Abstract_Observable $observable )
    dans ton interface et ton abstract

  3. #3
    Membre habitué Avatar de alejandro
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2004
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2004
    Messages : 167
    Points : 188
    Points
    188
    Par défaut
    Bonsoir,

    Je n'ai pas très bien compris ta réponse.

    Mon Front_Dispatcher étends une classe Abstract_Strategy qui n'a rien à voir avec la fonction update. Il implémente par contre une interface Interface_Observer dans laquelle est déclarée une fonction update :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    interface Interface_Observer
    {
        public function update( Interface_Observable $observable );
    }
    Donc ma fonction update que je dois déclarer dans mon Front_Dispatcher doit prendre comme argument un objet de type Interface_Observable.

    Mon Front_Router, lui, étends Abstract_Observable, qui implémente lui même le fameux Interface_Observable. Pourquoi ne puis-je pas mettre comme type obligatoire une classe qui implémente l'interface requise dans la déclaration de ma fonction update de mon Interface_Observer ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Front_Dispatcher
    extends Abstract_Strategy
    implements Interface_Observer
    {
        public function __construct( Front_Router $router )
        {
            $router->attach( $this );
            parent::__construct( $router );
        }
     
        public function update( Front_Router $observable )
        {
            print "updating std_dispatcher";
        }
    }
    Je pourrais simplement me dire que forcer un type implémentant l'interface requise ne fonctionne pas en PHP. Mais alors pourquoi ma fonction __construct( Front_Router $router ) fonctionne alors que dans Abstract_Strategy je demande un type Interface_Strategy ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    abstract class Abstract_Strategy
    implements Interface_Strategy
    {
        protected $_strategy;
     
        public function __construct( Interface_Strategy $strategy )
        {
            $this->_strategy = $strategy;
        }
     
        public function execute()
        {
            $this->_strategy->execute();
        }
    }
    Bien sûr là ça parait logique car Front_Router implémente Interface_Strategy.

    Ce que je ne comprends pas c'est pourquoi ça marche en haut et pas en bas sachant que en haut je déclare un type qui implémente la classe requise dans ma classe abstraite dont hérite mon Front_Dispatcher, alors qu'en bas je déclare un type qui étends une classe abstraite implémentant le type requis dans l'interface de mon Front_Dispatcher ?

Discussions similaires

  1. [C#] [Interface] Restreindre type avec héritage ?
    Par Error407 dans le forum Débuter
    Réponses: 2
    Dernier message: 05/12/2013, 18h33
  2. zoom dans une interface graphique type gui
    Par oregos dans le forum MATLAB
    Réponses: 1
    Dernier message: 25/04/2007, 12h45
  3. Double héritage, interface
    Par faulk dans le forum Langage
    Réponses: 7
    Dernier message: 18/04/2007, 02h46
  4. Erreur d'Héritage : Nom de Type Attendu
    Par Julien_C++ dans le forum C++Builder
    Réponses: 5
    Dernier message: 01/09/2006, 12h06
  5. [Tableaux] Type hinting en PHP ?
    Par Invité dans le forum Langage
    Réponses: 13
    Dernier message: 17/08/2006, 23h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo