在类内调用静态方法?


166

如何从同一类中的另一个方法调用静态方法?

$this->staticMethod();

要么

$this::staticMethod();

13
您可能对此感兴趣(selfvs. $this):stackoverflow.com/questions/151969/php-self-vs-this
Felix Kling 2010年

仅供参考,您的第一个示例是一个调用静态方法的实例变量,这是不可能的,因为静态方法是类的一部分,并且不能通过实例变量进行访问。
joejoeson 2010年

您可以立即删除$ this,如果仅使用静态方法且不存在实例,则该$ this无效。
malhal 2013年

Answers:


321

...但为什么?$ this-> staticMethod()也可以。您能解释一下为什么self :: staticMethod()更正确吗(如果正确)?
伊恩·邓恩

29
@Ian Dunn简而言之,$this仅当对象已实例化时存在,并且只能$this->method在现有对象中使用。如果您没有对象,而只是调用一个静态方法,并且要在同一类中调用另一个静态方法,则必须使用self::。因此,为避免潜在的错误(和严格的警告),最好使用self
jeroen 2012年

1
谢谢!在laravel中,我发现我不小心在使用的扩展控制器上调用了静态方法$this,但是直到将代码推送到时问题才浮出水面stage。没有错误返回,其值只是0。请谨慎使用self::
blamb

44

假设这是您的课程:

class Test
{
    private $baz = 1;

    public function foo() { ... }

    public function bar() 
    {
        printf("baz = %d\n", $this->baz);
    }

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

foo()方法内部,让我们看一下不同的选项:

$this->staticMethod();

这样调用staticMethod()作为实例方法,对吗?它不是。这是因为方法被声明为public static解释器,它将作为静态方法调用它,因此它将按预期工作。可以这样认为,这样做会使从代码中不太明显发生了静态方法调用。

$this::staticMethod();

从PHP 5.3开始,您可以$var::method()<class-of-$var>::; 尽管上面的用例仍然很不常规,但这很方便。因此,这为我们提供了调用静态方法的最常用方法:

self::staticMethod();

现在,你开始思考的是,之前::静态调用操作,让我给你举个例子:

self::bar();

这将打印出来baz = 1,这意味着$this->bar()self::bar()做完全相同的事情;那是因为::它只是一个作用域解析运算符。它的存在使parent::self::static::工作,给你访问静态变量; 方法的调用方式取决于其签名以及调用者的调用方式。

要查看所有这些操作,请参阅此3v4l.org输出


self::bar()似乎具有误导性-现在已弃用吗?(self::用于调用实例方法而不是静态方法)。
制造商史蒂夫

@ToolmakerSteve您会以哪种方式误导?
杰克

从逻辑上讲,self调用静态方法时没有。根据定义:静态方法可从任何地方调用,并且不接收“ self”参数。不过,我看到了该php语法的便利性,因此您不必编写MyClassName::。我习惯于使用静态类型的语言,在该类型中,必须为编译器提供当前范围内所有可用的变量,因此self::可以省略(等效项)。所以一个人说self instanceMethod; 没有理由说self staticMethod
ToolmakerSteve

15

这是一个很晚的回复,但在以前的回答中增加了一些细节

从同一类的另一个静态方法调用PHP中的静态方法时,区分self和类名很重要。

以下面的代码为例:

class static_test_class {
    public static function test() {
        echo "Original class\n";
    }

    public static function run($use_self) {
        if($use_self) {
            self::test();
        } else {
            $class = get_called_class();
            $class::test(); 
        }
    }
}

class extended_static_test_class extends static_test_class {
    public static function test() {
        echo "Extended class\n";
    }
}

extended_static_test_class::run(true);
extended_static_test_class::run(false);

此代码的输出是:

原班

扩展类

这是因为self引用代码所在的类,而不是从中调用代码的类。

如果要使用在继承原始类的类上定义的方法,则需要使用以下方法:

$class = get_called_class();
$class::function_name(); 

2
我发现这很有帮助。一个小问题,我不会说其他答案是“误导性的”。更准确地说,它们是“不完整的”;self::在静态方法A调用另一个静态方法B并且B已在子类中被覆盖的罕见情况下,它们没有解决(罕见的)问题的问题。恕我直言,将方法重写限制为“实例”方法比较容易混淆;在静态级别上谨慎使用该功能。换句话说,您的代码读者希望方法重写实例方法(这是OO编码的本质),而不是静态方法。
制造商史蒂夫

1
非常有用,并且该类的扩展不是原始类也很有意义。因此,有理由self在这种情况下不使用它。您已经声明了一个单独的类作为对第一类的扩展。使用self扩展的类中会提到扩展的类。这与其他答案并不矛盾,但肯定有助于说明的范围self
iyrin

2

在更高的PHP版本中self::staticMethod();也将不起作用。它将引发严格的标准错误。

在这种情况下,我们可以创建相同类的对象并按对象调用

这是例子

class Foo {

    public function fun1() {
        echo 'non-static';   
    }

    public static function fun2() {
        echo (new self)->fun1();
    }
}

可以这样做,尽管如果fun1不使用self,则使其成为实例方法是不合逻辑的。在php中执行此操作的正确方法是先声明public static function fun1,然后通过指定class:进行调用Foo::fun1。我敢肯定,这是解决该严格标准错误的预期方法。
ToolmakerSteve
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.