Почему я не могу перегружать конструкторы в PHP? - PullRequest
86 голосов
/ 31 января 2010

Я отказался от всякой надежды на то, что когда-нибудь смогу перегрузить мои конструкторы в PHP, поэтому я действительно хотел бы знать, почему .

Есть ли даже причина для этого? Создает ли он изначально плохой код? Является ли широко распространенным языковым дизайном запрет на его использование, или другие языки более хороши, чем PHP?

Ответы [ 12 ]

126 голосов
/ 01 февраля 2010

Вы не можете перегружать ЛЮБОЙ метод в PHP. Если вы хотите иметь возможность создавать экземпляр объекта PHP при передаче нескольких различных комбинаций параметров, используйте шаблон фабрики с закрытым конструктором.

Например:

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);
53 голосов
/ 31 января 2010

Вы можете использовать переменные аргументы для получения того же эффекта. Без строгой типизации не имеет смысла добавлять, учитывая аргументы по умолчанию и все остальные «обходные пути».

5 голосов
/ 28 июня 2016

Для полноты я предложу Свободные интерфейсы . Идея состоит в том, что, добавляя return $this; в конец ваших методов, вы можете объединять вызовы вместе. Так что вместо

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

(что просто не сработает), вы можете сделать:

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

Таким образом, вы можете выбрать, какие именно свойства вы хотите установить. Во многих отношениях это похоже на передачу массива опций вашему первоначальному вызову:

$car = new Car(['make' => 'Ford', 'seats' => 5]);
5 голосов
/ 31 января 2010

Истинная перегрузка действительно не поддерживается в PHP. Как упомянуто @Pestilence, вы можете использовать переменные аргументы. Некоторые люди просто используют ассоциативный массив различных вариантов, чтобы преодолеть это.

4 голосов
/ 13 февраля 2017

Руководство по PHP: Аргументы функций, значения по умолчанию

Я преодолел это, просто используя значения по умолчанию для параметров функции. В __constuct сначала перечислите обязательные параметры. Перечислите необязательные параметры после этого в общем виде $param = null.

class User
{
    private $db;
    private $userInput;

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

Это может быть создано как:

$user = new User($db)

или

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

Это не идеальное решение, но я сделал эту работу, разделив параметры на абсолютно обязательные параметры независимо от того, когда объект построен, и, как группа, дополнительные параметры, перечисленные в порядке важности .

Работает.

2 голосов
/ 26 декабря 2012

они говорят эту работу:

<?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
?>

и, кажется, все довольны этим, но для меня это не сработало ... если заставить его работать, то это тоже один из видов перегрузки ...

он берет все аргументы и передает их конструктору вторичной функции ...

1 голос
/ 19 октября 2017
<?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 голос
/ 02 декабря 2012

Вы можете использовать условные операторы в своем конструкторе и затем выполнять свою задачу. Например.

  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

и так далее ...

1 голос
/ 31 января 2010

Я действительно не эксперт по ООП, но, насколько я понимаю, перегрузка означает способность метода действовать по-разному в зависимости от параметров, которые он получает в качестве входных данных.Это очень возможно в PHP, вы просто не объявляете типы ввода, поскольку в PHP нет строгой типизации, и вся перегрузка выполняется во время выполнения, а не во время компиляции.

0 голосов
/ 18 августа 2018
<?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;

?>
...