1

コードを表示することで最もよく説明される奇妙な結果が得られます。

3 つのメソッドを持つクラス A を作成するとします。
addメソッド - 後で使用する他のクラス A インスタンスを追加する
_マジック メソッドを呼び出す- 動的変数とそこに値を追加する
_callStatic静的マジック メソッド - このメソッドは、より読みやすい A クラスを作成するのに役立ちます

したがって、クラスは次のとおりです。

class A_Class {

protected $name;
protected $varList;
protected $childs = array();

protected static $tabCount = 0;

public function __construct($name) {
    $this->name = $name;
}

public function add() {
    if (func_num_args()) { 
        $this->childs = array_merge($this->childs, func_get_args());
    }
    return $this;
}

public function __call($name, $arguments) {
    if (count($arguments) > 0) {
        $this->varList[$name] = $arguments[0];
    }
    return $this;
}

public static function __callStatic($name, $arguments) {
    return new A_Class($name);
}

}

そして今私がそれを使用するとき:

$a = A_Class::MyNameA();
$a->someDynamicVar("I am the var data");
$a->add(A_Class::ANotherNameA());
print_r($a);

正常に動作し、次の結果が得られます。

A_Class Object
(
    [name:protected] => MyNameA
    [varList:protected] => Array
        (
            [someDynamicVar] => I am the var data
        )

    [childs:protected] => Array
        (
        )
)

しかし、クラス A からの継承としてクラス B を作成しようとすると、次のようになります。

class B_Class extends A_Class {

public function __construct($name) {
    parent::__construct($name);
    $this->add(A_Class::NewAClass());
}

}

次のことを試してください。

$b = new B_Class("NewBClassInstance");
print_r($b);

再帰的な結果が得られます:

B_Class Object
(
    [name:protected] => B-MAN
    [varList:protected] => 
    [childs:protected] => Array
        (
            [0] => B_Class Object
 *RECURSION*
        )
)

私にはそれは奇妙です。
__callStatic が A クラスではなく B クラスから実行されているかのようです。

何か案は ?

4

1 に答える 1

1

たぶん、この例はあなたが理解するのを助けるでしょう:

<?php

class A
{
  public function __call($name, $args)
  {
    echo "__call\n";
  }

  static public function __callStatic($name, $args)
  {
    echo "__callStatic\n";
  }
}

class B extends A
{
  public function __construct()
  {
    A::callMe();
  }
}

new B();

これを実行した結果は次のとおりです。

__call

静的バージョンは呼び出されません。なんで?B は A の子孫であるため、とA::foo()の両方が存在する場合はあいまいな呼び出しに__callなり__callStaticます。

クラスのメンバー関数のコンテキスト内では、 「クラスで指定された静的メソッドを呼び出す」ことを意味しないClass::func() ことに注意してください。funcClass

それは単に「Classという名前の関数を呼び出す」ことを意味しfuncます。例えば:

class A
{
  public function foo() {}
}

class B
{
  public function foo() {}

  public function bar()
  {
    A::foo(); // call A's foo
  }
}

したがって、あなたの場合、__callメソッドは B のコンストラクターで呼び出されています。これは、このあいまいなケースで PHP が行うことです。$thisに渡されたものを返し$this->add()、効果的にこれを提供します: $this->add($this)B のコンストラクターで。

繰り返しますが、これらはいずれも、クラスのメンバー関数のコンテキスト内で「静的関数を呼び出す」ことを意味しません。

parent::foo();
self::foo();
static::foo();
A::foo();
B::foo();

それらはすべて、単に「::の左側にあるものによって参照されるように、クラス内の関数 foo を呼び出す」ことを意味します。通常、明示的なインスタンス関数または静的関数のいずれかがあるため、呼び出しがあいまいではありません。しかし、 と の両方がある場合、PHP はどちら__call__callStatic呼び出したいかを知る方法がなく、常に を選択し__callます。

于 2012-08-05T18:24:30.987 に答える