web-dev-qa-db-fra.com

Pourquoi ne puis-je pas surcharger les constructeurs en PHP?

J'ai abandonné tout espoir de pouvoir surcharger mes constructeurs en PHP, donc ce que j'aimerais vraiment savoir, c'est pourquoi .

Y a-t-il même une raison pour cela? Crée-t-il un code intrinsèquement mauvais? Est-ce une conception de langage largement acceptée pour ne pas le permettre, ou d'autres langues sont-elles plus agréables que PHP?

83
tom

Vous pouvez utiliser arguments variables pour produire le même effet. Sans typage fort, il n’a pas de sens d’ajouter, étant donné les arguments par défaut et tous les autres "solutions de rechange".

51
pestilence669

Vous ne pouvez surcharger aucune méthode en PHP. Si vous voulez pouvoir instancier un objet PHP en transmettant plusieurs combinaisons de paramètres, utilisez le modèle d'usine avec un constructeur privé. 

Par exemple:

public MyClass {
    private function __construct() {
    ...
    }

    public static function makeNewWithParameterA($paramA) {
        $obj = new MyClass(); 
        // other initialization
        return $obj;
    }

    public static function makeNewWithParametersBandC($paramB, $paramC) {
        $obj = new MyClass(); 
        // other initialization
        return $obj;
    }
}

$myObject = MyClass::makeNewWithParameterA("foo");
$anotherObject = MyClass::makeNewWithParametersBandC("bar", 3);
120
Alex Weinstein

La véritable surcharge n'est en effet pas prise en charge en PHP. Comme @Pestilence l'a mentionné, vous pouvez utiliser des arguments variables. Certaines personnes utilisent simplement un tableau associatif de diverses options pour surmonter ce problème.

5
Dominic Barnes

Pour être complet, je suggérerai Interfaces fluides . L'idée est qu'en ajoutant return $this; à la fin de vos méthodes, vous pouvez chaîner des appels. Donc au lieu de

$car1 = new Car('blue', 'RWD');
$car2 = new Car('Ford', '300hp');

(qui ne fonctionnerait tout simplement pas), vous pouvez faire:

$car = (new Car)
       ->setColor('blue')
       ->setMake('Ford')
       ->setDrive('FWD');

De cette façon, vous pouvez choisir exactement les propriétés que vous souhaitez définir. À bien des égards, cela revient à transmettre un tableau d’options à votre appel initial:

$car = new Car(['make' => 'Ford', 'seats' => 5]);
4
Codemonkey

ils disent ce travail:

<?php
class A
{
    function __construct()
    {
        $a = func_get_args();
        $i = func_num_args();
        if (method_exists($this,$f='__construct'.$i)) {
            call_user_func_array(array($this,$f),$a);
        }
    }

    function __construct1($a1)
    {
        echo('__construct with 1 param called: '.$a1.PHP_EOL);
    }

    function __construct2($a1,$a2)
    {
        echo('__construct with 2 params called: '.$a1.','.$a2.PHP_EOL);
    }

    function __construct3($a1,$a2,$a3)
    {
        echo('__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL);
    }
}
$o = new A('sheep');
$o = new A('sheep','cat');
$o = new A('sheep','cat','dog');

// results:
// __construct with 1 param called: sheep
// __construct with 2 params called: sheep,cat
// __construct with 3 params called: sheep,cat,dog
?>

et, il semble que tout le monde en soit satisfait, mais pour moi cela ne marchait pas ... Si vous le faites fonctionner, c'est une sorte de surcharge aussi ...

il prend tous les arguments et les passe au constructeur de la fonction secondaire ...

2
deadManN

PHP Manual: arguments de fonction, valeurs par défaut

J'ai surmonté cela simplement en utilisant les valeurs par défaut pour les paramètres de fonction. Dans __constuct, énumérez d'abord les paramètres requis. Répertoriez ensuite les paramètres facultatifs sous la forme générale $param = null.

class User
{
    private $db;
    private $userInput;

    public function __construct(Database $db, array $userInput = null)
    {
        $this->db = $db;
        $this->userInput = $userInput;
    }
}

Ceci peut être instancié comme:

$user = new User($db)

ou

$user = new User($db, $inputArray);

Ce n’est pas une solution parfaite, mais j’ai effectué ce travail en séparant les paramètres dans paramètres absolument obligatoires quel que soit le moment de la construction de l’objet et, en tant que groupe, facultatif). paramètres listés par ordre d'importance.

Ça marche.

2
Anthony Rutledge

Vous pouvez utiliser des instructions conditionnelles dans votre constructeur, puis exécuter votre tâche .

  class Example
  {
      function __construct($no_of_args)

      {// lets assume 2
          switch($no_of_args)
          {
              case 1:
                // write your code
              break;
              case 2:
                //write your 2nd set of code
              break;
              default:
           //write your default statement
         }
      }
   }

    $object1 = new Example(1);  // this will run your 1st case
    $object2 = new Example(2);  // this will run your 2nd case

etc...

1
DrGeneral
<?php
//php do not automatically call parent class constructor at all if child class has constructor so you have to call parent class constructor explicitly, however parent class constructor is called automatically if child class has no constructor
class MyClass 
{
    function construct1($value1)
    {
        echo "<br/> dummy constructor is called with 1 arguments and it is $value1";
    }
    function construct2($value1,$value2)
    {
        echo "<br/> dummy constructor is called with 2 arguments and it is $value1, $value2";
    }
    function construct3($value1,$value2,$value3)
    {
        echo "<br/> dummy constructor is called with 3 arguments and it is $value1, $value2 , $value3";
    } 
    public function __construct()
    {
        $NoOfArguments = func_num_args(); //return no of arguments passed in function
        $arguments = func_get_args();
        echo "<br/> child constructor is called $NoOfArguments";
        switch ($NoOfArguments) {
            case 1:
                 self::construct1($arguments[0]);
                break;
            case 2:
                self::construct2($arguments[0],$arguments[1]);
                break;

            case 3:
                self::construct3($arguments[0],$arguments[1],$arguments[2]);
                break;

            default:
                echo "Invalid No of arguments passed";
                break;
        }
    }


}
$c = new MyClass();
$c2 = new MyClass("ankit");
$c2 = new MyClass("ankit","Jiya");
$c2 = new MyClass("ankit","Jiya","Kasish");

?>

1

Je ne suis vraiment pas OOP - expert, mais si je comprends bien, surcharger signifie que la méthode peut agir différemment en fonction des paramètres qu'elle reçoit en entrée. C'est très possible avec PHP, vous ne déclarez pas les types d'entrée car PHP n'a pas de typage fort, et toute la surcharge est faite au moment de l'exécution au lieu de la compilation.

1
Matteo Riva

Autant que je sache, la surcharge de constructeur dans PHP n'est pas autorisée, tout simplement parce que les développeurs de PHP n'ont pas inclus cette fonctionnalité - il s'agit de l'une des nombreuses plaintes à propos de PHP.

J'ai entendu parler d'astuces et de solutions de contournement, mais la véritable surcharge au sens du terme OOP a disparu. Peut-être que dans les futures versions, cela sera inclus.

0
Charlie Salts

Je pense que nous pouvons également utiliser constructeur avec les arguments par défaut comme substitut potentiel à la surcharge de constructeur en PHP.

Néanmoins, il est vraiment dommage que la véritable surcharge de constructeur ne soit pas prise en charge en PHP.

0
Jay Nanavati
<?php

    class myClass {

        public $param1 = 'a';
        public $param2 = 'b';

        public function __construct($param1 = NULL, $param2 = NULL) {

            if ($param1 == NULL && $param2 == NULL) {
//                $this->param1 = $param1;
//                $this->param2 = $param2;
            } elseif ($param1 == NULL && $param2 !== NULL) {
//                $this->param1 = $param1;
                $this->param2 = $param2;
            } elseif ($param1 !== NULL && $param2 == NULL) {
                $this->param1 = $param1;
//                $this->param2 = $param2;                
            } else {
                $this->param1 = $param1;
                $this->param2 = $param2;
            }

        }

    }

//    $myObject  = new myClass();
//    $myObject  = new myClass(NULL, 2);
    $myObject  = new myClass(1, '');
//    $myObject  = new myClass(1, 2);

    echo $myObject->param1;
    echo "<br />";
    echo $myObject->param2;

?>
0
antelove