PHPUnit - 在静态方法中使用 $this 还是 self?

35

我不想写太长的文字,因为这是一个简单的问题。PHPUnit测试包含几个静态方法,例如所有这些\PHPUnit\Framework\Assert::assert*() 方法以及identicalToequalTo

我的IDE(带有IntelliSense /自动完成)不接受使用$this调用,但接受使用self。我学到静态函数应该通过类调用,而不是对象,所以使用self

更正确的方法是什么?

$this->assertTrue('test');
或者
self::assertTrue('test');

(如果"$this"更正确,您可以指出为什么我们不应该使用"self"吗?)


1
这是一个很好的问题。我也不完全理解为什么方法要是静态的,但是我看到的所有代码都使用$this而不是self。 - Serge Kuharev
3个回答

13
通常,self 仅用于引用静态方法和属性(尽管令人困惑的是,您可以使用 self 引用非静态方法,并且使用 self 调用的方法不引用 $this,也可以使用 $this 引用静态方法)。
<?php
class Test {
    public static function staticFunc() {echo "static ";}
    public function nonStaticFunc() {echo "non-static\n";}
    public function selfCaller() {self::staticFunc(); self::nonStaticFunc();}
    public function thisCaller() {$this->staticFunc(); $this->nonStaticFunc();}
}
$t = new Test;
$t->selfCaller();  // returns "static non-static"
$t->thisCaller();  // also returns "static non-static"

在处理$thisself时,继承是一个重要的概念。 $this始终指向当前对象,而self指的是使用self的类。现代PHP还通过static关键字包含了延迟静态绑定,它将以与$this相同的方式运行(并且应优先选择$this用于静态函数)。

<?php
class Person {
    public static function whatAmI() {return "Human";}    
    public function saySelf() {printf("I am %s\n", self::whatAmI());}
    public function sayThis() {printf("I am %s\n", $this->whatAmI());}
    public function sayStatic() {printf("I am %s\n", static::whatAmI());}
}

class Programmer extends Person {
    public static function whatAmI() {return "a programmer";}
}

$p = new Programmer;
$p->saySelf();    // returns "I am Human"
$p->sayThis();    // returns "I am a programmer"
$p->sayStatic();  // returns "I am a programmer"

关于 PHPUnit,特别是在 他们一直使用的方式 上似乎仍然如此!虽然根据他们的文档,使用静态方法应该能正常工作

这是一个非常好的答案。很抱歉我看得这么晚。现在我更理解这些标识符是如何工作的。但是,这个概念仍然让我感到困惑。为什么你可以在PHP中覆盖静态函数,以便返回值实际上在子类中发生变化?除了为什么可能性之外,为什么PHPUnit使用$this->而不是正确的static::访问呢?遗留代码? - Wolfsblvt
“Static”并不意味着它是不变的,就像普通英语用法一样。它只是描述了如何调用它(即不需要对象实例),因此在子类中重新定义它们没有问题。我不熟悉PHPUnit,但看起来这只是他们处理事情的方式。 - miken32
我仍然无法理解那是多么混乱和令人困惑,但我猜这就是PHP的本质。感谢您的快速回复,我想您的答案加上您在此处提供的链接应该足够为未来的读者提供信息了。我会将此标记为已解决。 - Wolfsblvt
好的,谢谢。我已经更新了答案,包括评论中的链接。 - miken32

3

那基本上只是我三年前回答的最后一句话,但好吧。 - miken32

2

PHPUnit 4.8.9:vendor/phpunit/phpunit/src/Framework/Assert.php

/**
 * Asserts that a condition is true.
 *
 * @param bool   $condition
 * @param string $message
 *
 * @throws PHPUnit_Framework_AssertionFailedError
 */
public static function assertTrue($condition, $message = '')
{
    self::assertThat($condition, self::isTrue(), $message);
}

在技术上,static::assertTrue()是正确的,但是assert方法的普遍用法是$this->assertTrue()


8
为什么要使用$this->assertTrue(),如果self::assertTrue()是更正确的方式呢? 我不明白这个问题的重点所在,这也是我提问的原因。 - Wolfsblvt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接