0

私は PHP を初めて使用し、PHP のバージョン (5.4.13) のバグである場合とそうでない場合がある奇妙な動作に遭遇しました。関数宣言で関数の引数の順序が問題になるケースを見つけました。次の例では:

class Book {
  function __construct() { }

  public static function withDescriptors($isNotOrmObject, $isArray, $isScalar) {
    $instance = new self();
    // initialization here
    return $instance;
  }
}

withDescriptors を呼び出すと、「配列から文字列への変換」例外が発生します。withDescriptors が呼び出されると、エラーがスローされます。withDescriptors が実際に実行されることはありません。ただし、オブジェクト パラメーターを配列パラメーターに切り替えると、問題が解決します。いえ

public static function withDescriptors($isArray, $isNotOrmObject, $isScalar){ ....

これは PHP の既知の特性ですか、それともバグですか?

より明示的に:

class Book {
  function __construct() { }

  public static function withDescriptors($isNotOrmObject, $isArray, $isScalar) {
    $instance = new self();
    // initialization here
    return $instance;
  }
}

$book = Book::withDescriptors($isNotORMobject, $isArray, $isScalar);

失敗し、

class Book {
  function __construct() { }

  public static function withDescriptors($isArray, $isNotORMobject, $isScalar) {
    $instance = new self();
    // initialization here 
    return $instance;
  }
}

$book = Book::withDescriptors($isArray, $isNotORMobject, $isScalar);

素晴らしい作品唯一の違いはパラメータ シーケンスです。「ここでの初期化」コードは同一です。

4

3 に答える 3

3

2 番目の例で警告が表示されない理由はObject、2 番目のパラメーターとして渡している がマジック__toString()メソッドを実装しているためです。PHP は強力な型付き言語ではありませんが、最近のバージョンでは型ヒントの機能が制限されています。

警告を説明するには;

function saySomething($shouldBeAString)
{
    echo $shouldBeAString
}

saySomething(array('hello'));

出力「配列」

そして警告array to string conversion

class Foo {
   public function __toString() {
       return 'Hi I am Foo';
   }
}

$bar = new Foo();

 saySomething($bar);

出力します

'Hi I am Foo'

警告なしに

前述のように、PHP は制限付きの型ヒントを提供します。必要な「クラス/オブジェクト型」と「配列」を引数として指定できますが、「string」、「int」、「bool」などのスカラー型は指定できません。

function (array $myarray) {
    // will only accept arrays
    // or something that implements array-access
}

function (Foo $var) {
    // Will only accept 'Foo' objects
}

ポリモーフィズム / 関数のオーバーロード

他の一部の言語では、同じメソッド/関数を複数回定義できますが、署名が異なります (他の引数の型)。PHP はこれを明示的にサポートしていません。

たとえば、他の言語では、これが許可されています。

function doSomething(string $arg1) { ......}

function doSomething(array $arg1) { .... }

function doSomething(string $arg1, string $arg2) { ... }

これらの言語では、引数の型と数に応じて、バリアント 1、2、または 3 が実行されます。関数/メソッドに一意の名前を付ける必要があるため、PHP はこれをサポートしていません。したがって、PHP は関数doSomething()が既に定義されていると文句を言います。

ただし、PHP で似たようなものをいくつかの方法で作成できます。

 // rename the functions/methods so that they have a unique name

function _doSomething1(string $arg1) { ......}

function _doSomething2(array $arg1) { .... }

function _doSomething3(string $arg1, string $arg2) { ... }


// create the 'wrapper' function *without arguments specified*
function doSomething() {

    // determin which variant should be executed
    $numargs = func_num_args();
    $args = func_get_args();

    if ($numargs == 2) {
        // 2 arguments -> variant 3
        return call_user_func_array('_doSomething3', $args);
    } else if {$numargs == 1) {
        if (is_array($args[0]) {
            // first argument is an array
            return call_user_func_array('_doSomething2', $args);
        } else {
            return call_user_func_array('_doSomething1', $args);
        }
    }
}

注:上記のコードは「偽の」コードであり、アイデアを説明するためのものです!

于 2013-04-07T11:47:19.897 に答える
1

一般に、関数の引数では順序が重要です。そうでないのは、引数が同じ型であるか、関数が get opt long のようなものを実装している場合だけです。

于 2013-04-07T10:53:30.703 に答える
-1

ここにはいくつかの良い答えがありますが、この特定の状況は PHP インタープリターのバグから発生しました。

于 2013-05-25T15:33:46.637 に答える