为什么我不能在PHP中重载构造函数?

时间:2010-01-30 21:12:20

标签: php oop overloading constructor

我已经放弃了能够在PHP中重载构造函数的所有希望,所以我真正想知道的是为什么

有没有理由呢?它是否会产生固有的错误代码?它被广泛接受的语言设计是不允许的,还是比PHP更好的其他语言?

15 个答案:

答案 0 :(得分:123)

你不能在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);

答案 1 :(得分:53)

您可以使用variable arguments产生相同的效果。如果没有强类型,在给定默认参数和所有其他“解决方法”的情况下添加它没有多大意义。

答案 2 :(得分:5)

PHP中确实不支持真正的重载。正如@Pestilence所提到的,你可以使用变量参数。有些人只是使用各种选项的关联数组来克服这个问题。

答案 3 :(得分:4)

为了完整起见,我建议Fluent Interfaces。我们的想法是,通过在方法的末尾添加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]);

答案 4 :(得分:2)

他们说这项工作:

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

并且,似乎每个人都对它感到高兴,但对我来说它没有用...... 如果你让它工作,它也是一种超载......

它需要所有的argoments并将它们传递给辅助函数构造函数...

答案 5 :(得分:2)

PHP Manual: Function Arguments, Default Values

我已经通过使用函数参数的默认值简单地克服了这个问题。在__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);

这不是一个完美的解决方案,但无论何时构建对象,我都通过将参数分成 绝对必需参数 来完成此工作,并且,作为一个组, 按重要性顺序列出的可选参数

有效。

答案 6 :(得分:1)

我真的不是OOP专家,但据我所知,重载意味着方法根据接收的参数作为输入采取不同的行为。这是非常有可能使用PHP,你只是不声明输入类型,因为PHP没有强类型,并且所有重载都是在运行时而不是编译时完成的。

答案 7 :(得分:1)

您可以在构造函数中使用条件语句,然后执行您的任务。 例如

  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

依旧......

答案 8 :(得分:1)

<?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");

&GT;

答案 9 :(得分:1)

您当然可以使用__call()和__callStatic()魔术方法重载PHP中的任何函数。 这有点棘手,但是实现可以完全满足您的需求。 这是PHP.net官方网站上的资源:

https://www.php.net/manual/en/language.oop5.overloading.php#object.call

这是适用于静态和非静态方法的示例:

class MethodTest
{
    public function __call($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling object method '$name' "
             . implode(', ', $arguments). "\n";
    }

    /**  As of PHP 5.3.0  */
    public static function __callStatic($name, $arguments)
    {
        // Note: value of $name is case sensitive.
        echo "Calling static method '$name' "
             . implode(', ', $arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('in object context');

MethodTest::runTest('in static context');  // As of PHP 5.3.0

您可以通过使用__construct()中的以下代码将其应用于构造函数:

$clsName = get_class($this);
$clsName->methodName($args);

非常容易。 而且,您可能想实现__clone()来使用您调用的方法创建该类的克隆副本,而无需在每个实例中都拥有您所调用的函数...

答案 10 :(得分:0)

据我所知,PHP中的构造函数重载是不允许的,因为PHP的开发人员不包含该功能 - 这是关于PHP的许多抱怨之一。

我听说过技巧和变通方法,但是缺少OOP意义上的真正重载。也许在将来的版本中,它将被包括在内。

答案 11 :(得分:0)

我认为我们也可以使用构造函数和默认参数作为PHP中构造函数重载的潜在替代。

但是,PHP中不支持真正的构造函数重载真的很难过。

答案 12 :(得分:0)

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

?>

答案 13 :(得分:0)

添加有关当前PHP完整性的答案,因为PHP的更高版本实际上可以以某种方式重载构造函数。以下代码将有助于理解,

<?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');
?>

输出:

__construct with 1 param called: sheep
__construct with 2 params called: sheep,cat
__construct with 3 params called: sheep,cat,dog

答案 14 :(得分:0)

 public function construct1($user , $company)
{
    dd("constructor 1");
    $this->user = $user;
    $this->company = $company;
}

public function construct2($cc_mail , $bcc_mail , $mail_data,$user,$company)
{
    dd('constructor 2');
    $this->mail_data=$mail_data;
    $this->user=$user;
    $this->company=$company;
    $this->cc_mail=$cc_mail;
    $this->bcc_mail=$bcc_mail;
}

public function __construct()
{
    $NoOfArguments = func_num_args(); //return no of arguments passed in function
    $arguments = func_get_args();
    switch ($NoOfArguments) {
        case 1:
             self::construct1($arguments[0]);
            break;
        case 5:
            self::construct2($arguments[0],$arguments[1],$arguments[2],$arguments[3],$arguments[4]);
            break;
        default:
            echo "Invalid No of arguments passed";
            break;
    }