4
<?php
class A {
  public function instanceFunc() {
    echo "instance";
  }

  public static function staticFunc() {
    echo "static";
  }
}

A::instanceFunc(); // instance
$a = new A();
$a->staticFunc(); // static

これは、PHP では静的メソッドとインスタンス メソッドにまったく違いがないことを意味します。Zend はそれについて不平を言うことさえありません (警告なし)。

Zend エンジンで。静的メソッドとインスタンス メソッドの両方がすべて zend_class_entry.function_table に保存されます。

なぜPHPはこのように振る舞うのですか? それはバグですか、それとも機能ですか?

4

3 に答える 3

3

これは、Does static method in PHP have any difference with nonstatic method?の重複の可能性があります。.

E_STRICT 警告が有効になっている場合はエラー メッセージが表示されます。そうでない場合は、非静的メソッドを静的であるかのようにサイレントに呼び出すことができます。ここと他の質問の回答で述べたように、実際の静的/非静的メソッドは、アクセスすることなく、$thisまたはself期待どおりに書かれていなければ、うまくいきません。

ドキュメントを参照してください: http://www.php.net/manual/en/language.oop5.static.php

ここで遊ぶものがあります:

http://codepad.org/Gbu9T6Zv

于 2011-04-19T17:35:56.487 に答える
2

以下のコードを実行してバックトレース出力を見ると、静的コンテキストで呼び出されたときに PHP が instanceFunc() を静的メソッドに変換することがわかります。ただし、インスタンス コンテキストでは、インスタンス呼び出しとして扱います。

ミックスにインスタンス変数を導入する (コメントアウトされた行を削除する) と、静的呼び出しから instanceFunc() を呼び出したときに致命的なエラーが発生します。

これは、PHP が本質的に静的である (インスタンス変数が処理されない) すべてのメソッドを静的コンテキストから呼び出すことを許可することを意味します。このコントラクトが破られるとすぐに、エラーが生成されます。したがって、静的関数の使用は、他のオブジェクト指向言語と調和するための唯一の良い習慣のようです。

staticFunc() に関しては、両方の呼び出しは、PHP がこれらを静的呼び出しとして解釈することを示しています。これは予想されることです。

class A {
  private $x = 5;
  private $y = 6;
  private $z;
  public function instanceFunc() {
    //$this->z = $this->y * $this->x;
    //echo $this->z;
    var_dump(reset(debug_backtrace()));
  }

  public static function staticFunc() {
    var_dump(reset(debug_backtrace()));
  }
}
$a = new A();
A::instanceFunc(); // static call of intended instance method
$a->instanceFunc(); // instance call of instance method
A::staticFunc();
$a->staticFunc();

出力例 (コメント付きで実行されるコード):

array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(19) ["function"]=>  string(12) "instanceFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=>  array(0) { } } 
array(7) { ["file"]=> string(59) "test.php" ["line"]=> int(22) ["function"]=> string(12) "instanceFunc" ["class"]=> string(1) "A" ["object"]=> object(A)#8 (3) { ["x:private"]=> int(5) ["y:private"]=> int(6) ["z:private"]=> NULL } ["type"]=> string(2) "->" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(24) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(26) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } }
于 2011-04-19T17:49:41.390 に答える
1

警告または少なくともエラーがスローされない理由がわかりません。ただし、静的とインスタンスにはいくつかの大きな違いがあります。静的メソッドは、非静的なクラス変数を使用できません。これは、非静的なパブリック/プライベート変数を追加し、それをエコーし​​てstaticFuncエラーをスローすることで簡単にテストできます。

主な目標は、この 2 つの違いを理解し、適切に使用することだと思います。PHP が少なくとも通知を出さない理由については、私にはわかりませんが、おそらくそれはそのゆったりとした性質によるものです。私はそれについてより多くの知識を持っている誰かが与えることができる反応に興味があります.これはちょっとした追加情報です.

完全なエラー報告をオンにしてテストしましたが、通知や警告が実際にスローされないことは確かです。


アップデート

いくつかのテストを行うと、マークされていない静的関数を静的関数として呼び出すと、まだプライベート/パブリック変数を使用できないようです。通常の関数の場合、エラーが発生する可能性が最も高くなります。これが、エラーまたは通知がスローされなかった理由である可能性があります。ただし、そのような方法でマークされていない静的関数を使用することは確かに良くないため、それについて何かをスローすることは良いことです.

于 2011-04-19T17:23:12.160 に答える