web-dev-qa-db-ja.com

PHPでコンストラクターをオーバーロードできないのはなぜですか?

PHPでコンストラクターをオーバーロードできるようになるという希望をすべて捨てたので、本当に知りたいのはwhyです。

それには理由さえありますか?本質的に悪いコードを作成しますか?それを許可しないことは広く受け入れられている言語設計ですか、または他の言語はPHPよりも優れていますか?

88
tom

可変引数 を使用して、同じ効果を得ることができます。強い型付けがなければ、デフォルトの引数と他のすべての「回避策」を考えて、追加するのはあまり意味がありません。

53
pestilence669

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);
128
Alex Weinstein

完全を期すために、 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]);
5
Codemonkey

真のオーバーロードは、PHPでは実際にサポートされていません。 @Pestilenceが述べたように、可変引数を使用できます。これを克服するために、さまざまなオプションの連想配列を使用する人もいます。

5
Dominic Barnes

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

これは完璧な解決策ではありませんが、パラメーターを絶対に必須のパラメーターに分離することでこの作業を行いましたオブジェクトがいつ構築されても、グループとして、重要度の順にリストされたオプションのパラメーター

できます。

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

?>

彼らはこの作品を言う:

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

そして、誰もがそれで満足しているように見えますが、私にとってはうまくいきませんでした...あなたがそれを働かせたら、その一種の過負荷も...

すべての引数を取り、それらを二次関数コンストラクタに渡します...

2
deadManN

コンストラクターで条件ステートメントを使用して、タスクを実行できます。例えば。

  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
DrGeneral

私は本当にOOPエキスパートではありませんが、私が理解しているようにオーバーロードは、入力として受け取るパラメーターに応じて異なる動作をするメソッドの能力を意味します。これはPHPでは非常に可能ですが、PHPには強い型付けがなく、すべてのオーバーロードはコンパイル時ではなく実行時に行われるため、入力タイプを宣言しないでください。

1
Matteo Riva

私の知る限り、PHPでのコンストラクタのオーバーロードは許可されていません。単にPHPの開発者がその機能を含んでいなかったためです。 PHPに関する苦情。

トリックや回避策について聞いたことがありますが、OOPの意味での真のオーバーロードは欠落しています。将来のバージョンでは含まれる可能性があります。

0
Charlie Salts

PHPでのコンストラクタのオーバーロードの潜在的な代替としてconstructor with default argumentsも使用できると思います。

それでも、実際のコンストラクタのオーバーロードが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