【问题标题】:What is going on here in PHP with classes?PHP与类在这里发生了什么?
【发布时间】:2010-10-02 12:49:00
【问题描述】:

如果我有此代码,则会回显字符串“test”。这是在 PHP 5.3 中。这是一些不应该依赖的疏忽,还是在 PHP 中实现多重继承的某种方式?

class Test1
{
    function getName()
    {
        return $this->name;
    }
}

class Test2
{
    public $name = 'test';

    function getName()
    {
        return Test1::getName();
    }
}

$test = new Test2;
echo $test->getName();

编辑:

正如 GZipp 指出的 cmets,这实际上是记录在案的行为。请参阅此页面:http://us2.php.net/manual/en/language.oop5.basic.php 和标题“示例 #2 $this 伪变量的一些示例”。

A 类和 B 类与我上面的两个测试类和行的关系相似

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

显示与我的示例大致相同的结果。

【问题讨论】:

  • WTH?这确实有效! (我试过了)......它不应该(基于 PHP 的继承规则和静态调用)。对Test1::getName() 的调用确实会产生E_STRICT 错误,但是如果您有error_reporting 以不显示严格的错误,它可以工作......我想你偶然发现了一个错误......但话又说回来,它也适用于5.2。 .. 很奇怪...
  • 我会说这是一个错误.....我预计 100% 的回报将是 NULL
  • 但报告已提交:bugs.php.net/bug.php?id=52969
  • 如果您愿意,可以将其称为错误,但这是记录在案的行为。 us2.php.net/manual/en/language.oop5.basic.php
  • 好吧,如果这真的被人知道并记录在案,我必须得出这样的结论:PHP 在这一点上确实很烂。

标签: php oop inheritance


【解决方案1】:

要明确一点 - 这不是继承。 Test2 不扩展 Test1。您静态引用了 Test1 类的公共方法。

尽管如此,它返回 'test' 的事实至少可以说很有趣。我看到它在哪里散发出继承的想法。

如果您找不到合适的答案,我会将您的代码作为错误提交。

更新

它看起来像在幕后,即使您静态引用了 Test1 的方法,它仍然被称为 Test2。最后,这是未定义的行为,上面提到的问题确实会引发严格的警告。仍然很奇怪,我个人同意它不应该工作。但只是为了更深入地了解它正在使用哪个对象。

class Test1 {
    function getName() {
        echo get_class($this);
        return $this->name;
    }
}
// ...
$test = new Test2;
echo $test->getName();

// echoes 'Test2 test'

【讨论】:

  • $this in Test1::getNameTest2 类的对象...这是不可能的,因为这两个类都没有扩展另一个类。我倾向于错误的观点,但它似乎已经存在了一段时间(至少从 5.2.2 开始,我拥有的最古老的测试安装)......
  • 不,这不是继承。但它似乎提供了一些允许水平代码重用的方法,就像特征那样,但更有限。我希望他们不要“修复”它,因为它偶尔会有用
  • 如果您有需要,请使用它。这绝对很有趣。只需了解到目前为止的普遍共识是它是一个错误。哪一天可能会解决。
【解决方案2】:

PHP 允许像调用静态方法一样调用非静态方法——这是一个特性。 PHP 将$this 作为隐式参数传递给此类调用。就像以正常方式调用方法时一样。

但显然 PHP 不会检查静态调用的类是否继承了当前类 - 这就是错误。

这就是你可以想到的 PHP 所做的事情:

function Test1->getName($this = null) {
    return $this->name;
}

function Test2->getName($this = null) {
    return Test1->getName($this);
}

$test = new Test2;
echo $test->getName($test);

这种行为是错误的。正确的Test2->getName 是:

function Test2->getName($this = null) {
    return $this instanceof Test1 ? Test1->getName($this) : Test1->getName();
}

【讨论】:

    【解决方案3】:

    这一定是一个错误。 100%。

    1. 这不是继承。
    2. 您应该无法调用 Test1::getName() 作为 getName() 在 Test1 不是静态的
    3. 即使你 可以调用它,$this->name 应该 无法访问中的值 测试 2。

    这打破了 OO 的许多规则,我对它是如何通过测试感到非常困惑。好吧,不要找到它!

    【讨论】:

    • 这应该工作的唯一时间是如果 Class3 扩展 Class2 扩展 Class1。然后,您可以通过调用 Class1::method() 从 Class3 中访问 Class1 的方法之一,就像您可以通过调用 parent::method() 访问未知父类的方法一样......但就目前而言,它非常糟糕......
    • @ircmaxwell - 为什么在继承示例中静态引用父类方法?你知道 PHP 中的 :: 是一个静态引用,对吧?您上面关于继承的评论应该真正使用$this->method();。您不需要扩展一个类来静态引用其中一个方法。您只需将该方法定义为static
    • 嗯,你可以通过调用parent::method()来访问一个父方法,如果你需要访问一个被覆盖的方法(例如,父定义getName,实例化的类覆盖它) . 您可以通过调用parent::getName()) 访问父版本... .
    • 嗯,2 是 PHP 中的预期行为。问题是3。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 2013-11-03
    • 2012-02-16
    • 1970-01-01
    • 2010-12-14
    相关资源
    最近更新 更多