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 :

un tableau en argument [PHP 5.5]


Sujet :

Langage PHP

  1. #1
    Membre éclairé
    Avatar de wafiwafi
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    500
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 500
    Par défaut un tableau en argument
    Bonjour,
    J’ai un un problème sur le typage que j’explique sous forme d’exemple:

    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
    16
    17
    18
    19
    20
    class A 
    {
    public function FA()
      {
    //Bla Bla bla
       }
     
    }
     
    class B 
    {
    //fonction ayant comme argument un tableau
    public function FB(array $tab)
    {			 
    for ($numero = 0; $numero < 4; $numero++)
    	{
    	$tab[$numero]->FA();		
    	}
    }
    }
    Dans la méthode FB, sur les élément du tableaux ( dans mon cas des objets de type A) la méthode FA est appelée. Ma question est : Comment le compil va savoir que dans le tableau il y a des objets qui peuvent appeler cette méthode (FA) ? je ne peux pas typer le tableau dès le début au lieu de array ?
    Merci à vous

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Mai 2008
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 1 576
    Par défaut
    Citation Envoyé par wafiwafi Voir le message
    Comment le compil va savoir que dans le tableau il y a des objets qui peuvent appeler cette méthode (FA) ? je ne peux pas typer le tableau dès le début au lieu de array ?
    L'interpréteur (et non le compilateur) ne sait pas à l'avance. Il va juste essayer de lancer la méthode FA de l'objet. Si l'objet a cette méthode, ça marche; si l'objet n'a pas la méthode, il lance une erreur.

    Tu ne peux pas typer le tableau (il y avait une RFC de ce genre pour PHP 5.6 mais elle a été rejetée). C'est donc à toi de vérifier chaque élément du tableau en utilisant instanceof.

  3. #3
    Membre éclairé
    Avatar de wafiwafi
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    500
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 500
    Par défaut
    ok, ça m'est très utile.
    Merci beaucoup.

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 020
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 020
    Par défaut
    L'idéal serait de ne pas passer de tableau à ta fonction mais une instance d'une classe C implémentant (au minimum) l'interface ArrayAccess. L'intérêt est que le contrôle du type des items se fait dans la classe en question au lieu de se faire dans la classe B où il n'a rien à faire. La fonction FB se contentera de contrôler avec un typehint que le paramètre est bien une instance de C. Exemple:
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    class C implements ArrayAccess {
      private $_array = [];
     
      public function offsetSet($offset, $value) {
        // on contrôle le type à chaque ajout.
        // NB: ici on ne peut pas utiliser de typehint car l'interface ArrayAccess l'interdit.
        if (!$value instanceof A)
          throw new InvalidArgumentException('La valeur n\'est pas une instance de A');
     
        if (is_null($offset))
          $this->_array[] = $value;
        else
          $this->_array[$offset] = $value;
     
      }
     
      public function offsetExists($offset) {
        return isset($this->_array[$offset]);
      }
     
      public function offsetUnset($offset) {
        unset($this->_array[$offset]);
      }
     
      public function offsetGet($offset) {
        return isset($this->_array[$offset]) ? $this->_array[$offset] : null;
      }
    }
     
    class B
    {
      public function FB(C $tab) {
        for ($numero = 0; $numero < 4; $numero++) {
          $tab[$numero]->FA();
        }
      }
    }
     
    $tab = new C;
     
    try {
      $tab[] = new A;
      $tab[] = new A;
      $tab[] = new A;
      $tab[] = new A; // $tab[] = 6;
    } catch (InvalidArgumentException $e) {
      echo $e->getMessage() . ':' . PHP_EOL;
      echo $e->getTraceAsString() . PHP_EOL;
      exit(1);
    }
     
    $objB = new B;
    $objB->FB($tab);
    Si tu as besoin d'autres aspects du type Array, tu peux implémenter l'interface Iterator (qui permet notamment de parcourir une instance de C avec foreach) où carrément en la faisant hériter de la classe ArrayObject.

  5. #5
    Membre éclairé
    Avatar de wafiwafi
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    500
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 500
    Par défaut
    Remarquable!
    J'applique ça et je reviens mettre un mot.
    Un grand merci

  6. #6
    Membre éclairé
    Avatar de wafiwafi
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    500
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 500
    Par défaut
    Bonjour,

    La classe C se focalise sur les instances de type A puisqu'elle procède à une vérification.
    J'aimerais rendre cet aspect polymorphe! C'est à dire à la création d'un objet C, j'indique le type à vérifier. possible?
    Merci
    Cordialement

  7. #7
    Membre émérite Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Par défaut
    Bonjour,

    Je suis pas sur de la question, si tu peux poster du code ça sera plus clair...

    De ce que je comprends, tu veux faire un type hint dynamique basé sur un attribut de ta classe (ou en C++ un template par exemple). Ce n'est pas possible.

    Ce que tu peux faire par contre, c'est soit utiliser assert (assez couteux malheureusement < PHP 7) et mettre un instanceof dedans (ou un is_a). En 5.5, tu peux faire la même chose avec une exception plutôt, question de rapidité

  8. #8
    Membre éclairé
    Avatar de wafiwafi
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    500
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 500
    Par défaut
    Oui, c'est bien ça.
    Je vais suivre tes préconisations.
    Sinon, tout marche super bien. mes objets de type C se comportent exactement comme des tableaux et c'est bien pratique.
    Merci à tous

  9. #9
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 020
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 020
    Par défaut
    Tu peux très bien passer une chaîne avec un nom de classe (ou un type basique) au constructeur:
    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
    16
    class C implements ArrayAccess {
      private $_array = [];
      private $_type;
     
      public function __construct($type='A') {
          // TODO: ajouter un test pour vérifier l'existence de la classe avec class_exists()
          // ou rendre ce test optionnel avec un deuxième paramètre.
          // Autoriser les types de base
          $this->_type = $type;
      }
     
      public function offsetSet($offset, $value) {
     
        if (!$value instanceof $this->_type)
          throw new InvalidArgumentException('La valeur n\'est pas une instance de ' . $this->_type);
        ...

  10. #10
    Membre émérite Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Par défaut
    Juste un détail CosmoKnacki : essaye de respecter PSR-2 quand tu proposes du code aux gens sur les forums, c'est le standard actuellement en PHP...

    Les noms de propriété NE DEVRAIENT PAS être précédés d'un sous-tiret pour indiquer la visibilité protégée ou privée.
    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
    16
    17
    18
    19
    20
     
    class C implements ArrayAccess
    {
        private $array = [];
        private $type;
     
        public function __construct($type = 'A')
        {
            // TODO: ajouter un test pour vérifier l'existence de la classe avec class_exists()
            // ou rendre ce test optionnel avec un deuxième paramètre.
            // Autoriser les types de base
            $this->type = $type;
        }
     
        public function offsetSet($offset, $value)
        {
            if (!$value instanceof $this->type) {
                throw new InvalidArgumentException("La valeur n'est pas une instance de {$this->type}");
            }
            ...

  11. #11
    Membre éclairé
    Avatar de wafiwafi
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    500
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 500
    Par défaut
    Que du bonheur!
    Merci à la communauté!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. passer un tableau en argument
    Par lanfeust42 dans le forum Langage
    Réponses: 3
    Dernier message: 29/08/2006, 19h32
  2. tableau comme argument à vsprintf
    Par Steffane dans le forum C
    Réponses: 11
    Dernier message: 21/07/2006, 11h14
  3. [String] formater une chaine avec un tableau d'argument
    Par jakouz dans le forum Collection et Stream
    Réponses: 6
    Dernier message: 14/04/2006, 15h19
  4. passer un tableau d'arguments à un thread
    Par madimane dans le forum POSIX
    Réponses: 5
    Dernier message: 14/04/2006, 07h08
  5. fonction renvoyant un tableau en argument
    Par Jones dans le forum Langage
    Réponses: 6
    Dernier message: 30/09/2002, 18h20

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