【问题标题】:Accessing incorrect static property from within non static method in PHP从 PHP 中的非静态方法中访问不正确的静态属性
【发布时间】:2013-12-17 19:27:44
【问题描述】:

我在 PHP 中遇到了一些看起来很奇怪的事情。我正在尝试从非静态方法访问静态属性。我需要使用 static 关键字来访问此属性,因为它可以在每个子类中具有不同的值。

但是,它根本没有访问预期类的属性,而是访问调用类的属性。这对我来说似乎是一个错误,但如果不是,我想知道是否有人可以向我解释这种行为并解释我如何访问这个静态属性。

我在这里的期望是静态属性 $why 将从 B 类中获取。我很困惑为什么它会从 A 类中获取。

<?php

error_reporting(E_ALL & ~E_STRICT);

class A
{
    public static $why = "Really don't want this value. Bug?";
    public function callB()
    {
        $B = new B;
        $B::getWhy(); // PHP Bug? 
        $B->getWhy();
        $B::getWhyStatic();
        $B::getWhyStaticSelf();
    }
}

class Base {

    protected static $why = "Don't want this value";

    public static function getWhyStatic()
    {
        echo static::$why . "<BR>\n";    
    }

    public static function getWhyStaticSelf()
    {
        echo self::$why . "<BR>\n";    
    }

    public function getWhy()
    {
        echo static::$why . "<BR>\n";
    }
}

class B extends Base
{
    protected static $why = "Want this value?";
}

$A = new A;
$A->callB();

【问题讨论】:

  • 您的问题需要更清楚,例如,您希望访问哪个属性,而您访问的是哪个属性?
  • 添加了一些额外的说明。希望取消投票。
  • 删除了反对票,请参阅下面我编辑的答案,将$B::bah() 更改为$B-&gt;bah() 应该可以解决它
  • 我不认为这是重复的。上面是问为什么可以静态调用非静态方法。我在问为什么,当它们被静态调用时,为什么会返回不正确的静态属性。

标签: php late-static-binding


【解决方案1】:

$B::bah(); 应该是$B-&gt;bah();,因为bah 不是静态函数。

【讨论】:

  • 是的,我意识到这一点。我正在处理一些遗留代码,其中一些以前的静态方法已转换为非静态方法。在进行一些清理时,我注意到了这种奇怪的行为,并想知道 PHP 中是否存在错误。如果这是无法做到的事情,我希望 PHP 会抛出 E_ERROR 而不是 E_STRICT。
【解决方案2】:

这并不是真正的错误,但更多的是文档中并未真正涵盖的结果。我自己做了一些研究并玩了一些东西,我想我已经弄明白了,但我不能 100% 确定,因为没有官方文本涵盖这一点。

我得到的印象是,当您尝试在实例上调用静态方法时,它等同于使用类名,而 PHP 实际上会以这种方式调用它,而不是实例。例如$B::getWhy();B::getWhy() 相同,无论您是否传递实例,核心代码都会看到它。

您遇到的问题是您将非静态方法作为静态方法调用。由于方法的工作方式,它们需要一个范围来提供诸如self$this 之类的东西。现在,通过像调用静态方法一样调用非静态方法,并考虑到上面关于 PHP 实际运行代码的方式,唯一可用的范围是类 A 的范围,因为这是范围你打电话给它。这意味着后期静态绑定发生并由于范围更改而将B::$why 覆盖为A::$why,这正是后期静态绑定应该实现的目标。

我希望这是有道理的,如果有任何不清楚的地方,请告诉我,我会尽力解释。

有关更多信息,还有另一个问题实际上解决了这个问题:Calling non static method with "::"

【讨论】:

  • 更改原始代码并不能解释原始行为。我认为,这已经被要求了。
  • 这里需要后期静态绑定,从 static:: 切换到 self:: 不是一个选项,除非 self:: 在非静态方法中的行为与静态方法不同。
  • 为什么需要后期静态绑定?您需要在原始帖子中添加更多信息,因为 B 不是 A 的子代,而是完全独立的类。
  • 我已将我的示例更新为希望更清楚地说明问题的示例。
  • 我已经更新了我的答案,不要把它当作福音,但这是我现在唯一能得到的有意义的东西。
猜你喜欢
  • 2013-02-13
  • 1970-01-01
  • 2012-03-30
  • 2018-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
相关资源
最近更新 更多