【问题标题】:PHPUnit - Use $this or self for static methods?PHPUnit - 使用 $this 或 self 作为静态方法?
【发布时间】:2015-07-14 11:56:42
【问题描述】:

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

我的 IDE(带有 IntelliSense/autocompletion)不接受带有 $this 的调用,而是带有 self.我了解到静态函数应该通过类调用,而不是对象,所以self

什么更正确?

$this->assertTrue('test');

self::assertTrue('test');

?

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

【问题讨论】:

  • 这是个好问题。我也不完全理解为什么方法是静态的,但是我看到的所有代码都使用 $this 而不是 self。

标签: php unit-testing oop phpunit self


【解决方案1】:

通常,self 仅用于引用静态方法和属性(尽管您可以使用self 引用非静态方法,使用$this 引用静态方法,这很容易混淆,前提是使用self 调用的方法不引用$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 关键字包含 late static binding,其运行方式与静态函数的 $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 Male extends Person {
    public static function whatAmI() {return "Male";}
}

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

特别是对于 PHPUnit,他们似乎只是在做事the way they've always done them!虽然根据他们的文档,your code should work fine 使用静态方法。

【讨论】:

  • 这是一个非常好的答案。抱歉这么晚才看到。现在我更了解这些标识符是如何工作的。但是,这个概念仍然让我感到困惑。为什么你可以覆盖 PHP 中的静态函数,以便返回值在子项中实际发生变化?除了为什么这是可能的,为什么 PHPUnit 使用 $this-&gt; 而不是正确的 static:: 访问呢?遗留代码?
  • “静态”并不意味着它是不变的,就像在常规英语用法中一样。它只是describes how it's called(即不需要对象的实例),因此在子类中重新定义它们没有问题。我对 PHPUnit 不熟悉,但看起来它只是 the way they do things
  • 我仍然无法理解这是多么肮脏和混乱,但我想这就是 PHP 的本质。感谢您的快速回复,我想您的回答与您在此处提供的链接相结合应该为未来的读者提供足够的信息。我会将其标记为已解决。
  • 好的,谢谢。我已经更新了答案以包含来自 cmets 的链接。
【解决方案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-&gt;assertTrue()

【讨论】:

  • 但是为什么你应该使用$this-&gt;assertTrue(),如果self::assertTrue() 是更正确的方式呢?我不明白这一点。这就是我提出问题的原因。
【解决方案3】:

phpunit 文档说您可以使用其中任何一种,但并不提倡使用其中一种。所以你选择! https://phpunit.readthedocs.io/en/9.2/assertions.html

【讨论】:

    猜你喜欢
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 2012-06-30
    相关资源
    最近更新 更多