php内部——php的静态成员和实例成员似乎没有什么不同.为什么PHP会这样做(没有警告)


php internals - PHP's static member and instance member seems no different. Why PHP does so(Without warning)?

<?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是这样的?是bug还是特性?

这是PHP中静态方法和非静态方法有什么区别吗?

如果您启用了E_STRICT警告,您将得到一个错误消息,否则,您可以静默地调用非静态方法,就好像它是静态的一样。正如在这里的答案和另一个问题中提到的,如果不访问$thisself,现实世界的静态/非静态方法将不会走得太远。

参考文档:http://www.php.net/manual/en/language.oop5.static.php

这里有一些东西可以玩:

http://codepad.org/Gbu9T6Zv

如果您尝试运行下面的代码并查看反向跟踪输出,您将看到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) { } }

我不知道为什么它不会抛出一个警告或至少一个错误。但是,静态和实例之间有一些主要的区别。静态方法不能使用非静态的类变量。这很容易通过添加一个非静态的公共/私有变量来测试,并试图在会抛出错误的staticFunc中响应它。

我认为主要目标是了解两者之间的区别以及如何正确使用它们。至于为什么PHP至少不发出一个Notice,我不知道,也许是由于它的懒散的性质。我对有更多知识的人能给出的回答很感兴趣,这只是一点额外的信息。

我确实在完整的错误报告中进行了测试,并且确实没有抛出通知或警告。


做一些测试,似乎当你调用一个未标记的静态函数作为静态函数,你仍然不能使用私有/公共变量。对于正常的函数,很可能会出错。这可能就是为什么从未抛出错误或通知的原因。然而,如果它能抛出一些东西就好了,因为以这种方式使用未标记的静态函数肯定是不好的。