PHP 错误地处理了我的静态调用

标签 php class methods static php-5.3

我在 PHP 5.3 上遇到了问题。我需要使用 __callStatic 调用方法,但如果我在实例化对象中使用它,PHP 会改为调用 __call

上面是一个真实的例子:

<?php

    class A {
        function __call($method, $args){
            // Note: $this is defined!
            echo "Ops! Don't works. {$this->c}";
        }

        static function __callStatic($method, $args){
            echo 'Fine!';
        }
    }

    class B extends A {
        public $c = 'Real Ops!';

        function useCallStatic(){
            static::foo();
            // === A::foo();
            // === B::foo();
        }
    }

    $foo = new B();
    $foo->useCallStatic();

    // This works:
    // B::foo();

?>

打印:糟糕!不工作。真正的行动!

请注意,我从 new B() 调用了 useCallStatic。如果我直接调用,效果很好,如 B::foo()

我能做些什么让它工作正常?

最佳答案

仔细想想,还真不是bug。但这绝对是不直观的。

<?php
class A
{
  public function foo()
  {
    static::bar();
  }

  public function bar()
  {
    echo "bar()\n";
  }
}

$a = new A();
$a->foo();

这是有效的,并调用 bar()。这并不意味着静态调用 bar。意思是查找当前类名,如果存在就调用函数bar,不管是不是静态函数。

再澄清一点:你认为 parent::bar() 意味着调用名为 bar() 的静态函数吗?不,这意味着调用任何名为 bar() 的函数。

考虑:

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

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

  function regularMethod()
  {
    echo "regularMethod()\n";
  }

  static function staticMethod()
  {
    echo "staticMethod()\n";
  }

}

class B extends A
{
  function foo()
  {
    parent::nonExistant();   
    static::nonExistant();
    parent::regularMethod();
    parent::staticMethod(); 
  }
}

$b = new B();
$b->foo();

parent::nonExistant() 方法调用 A::__call()static::nonExistant() 也是如此。调用 A::__callStatic() 进行任一 调用同样有效! PHP 无法知道您要调用哪一个。但是,根据设计,从此类上下文调用时,PHP 赋予 __call 优先权。

parent::regularMethod() 调用非静态函数 regularMethod()。 (同样,:: 运算符并不意味着“调用此静态函数。”)同样,parent::staticMethod() 调用 A::staticMethod() 正如人们所期望的那样。

解决您的问题:

您可以在继承的类中手动调用 self::__callStatic('foo')

或者在 A 类的 __call 方法中过滤已知列表并调用 self::__callStatic

function __call($f, $a)
{
  if ($f == 'foo')
    return self::__callStatic($f, $a); 
  else
  {
  }
}

这很丑陋,但至少扩展类的人不需要做任何特别的事情。

关于PHP 错误地处理了我的静态调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6181603/

相关文章:

javascript - 为什么一个外部更新的数组不会自动刷新?

stdin 的 C++ IO 优化和字符串处理

java - Java 8 中接口(interface)方法的隐式声明是什么?

java - 使用 Java ( android ) 中其他 Activity 的方法

c# - 如何在不到 6 小时的执行时间内测试 500 万亿个组合

php - WordPress 类别 php 查询内存不足?

php - 如何从组件发送和获取数据到php? ionic 2

PHPDoc - 在函数中没有参数的情况下记录@param?

python - 在类中实现微调器类型对象作为子进程

c++ - 试图访问一个类中另一个类的成员函数