php 使用双冒号 (::) 调用非静态方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3754786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 10:59:28  来源:igfitidea点击:

Calling non-static method with double-colon(::)

phpstatic

提问by NakaBr

Why can't I use a method non-static with the syntax of the methods static(class::method) ? Is it some kind of configuration issue?

为什么我不能使用具有方法 static(class::method) 语法的非静态方法?这是某种配置问题吗?

class Teste {

    public function fun1() {
        echo 'fun1';
    }
    public static function fun2() {
        echo "static fun2" ;
    }
}

Teste::fun1(); // why?
Teste::fun2(); //ok - is a static method

回答by davidtbernal

PHP is very loose with static vs. non-static methods. One thing I don't see noted here is that if you call a non-static method, nsstatically from within a non-static method of class C, $thisinside nswill refer to your instance of C.

PHP 在静态方法和非静态方法方面非常松散。我在这里没有看到的一件事是,如果您ns从 class 的非静态方法中静态调用非静态方法C,则$thisinsidens将引用您的C.

class A 
{
    public function test()
    {
        echo $this->name;
    }
}

class C 
{
     public function q()
     {
         $this->name = 'hello';
         A::test();
     }
}

$c = new C;
$c->q();// prints hello

This is actually an error of some kind if you have strict error reporting on, but not otherwise.

如果您有严格的错误报告,这实际上是某种错误,但不是其他情况。

回答by David Titarenco

This is a known "quirk" of PHP. It's by design to prevent back-propagation for figuring out if some time ago we actually instantiated an object or not (remember, PHP is interpreted, not compiled). However, accessing any non-static member the via scope resolution operator if the object is not instantiated will issue a fatal error.

这是 PHP 的一个众所周知的“怪癖”。它的设计目的是为了防止反向传播,以确定一段时间前我们是否真的实例化了一个对象(请记住,PHP 是解释的,而不是编译的)。但是,如果对象未实例化,则通过范围解析运算符访问任何非静态成员将发出致命错误。

Courtesy of PHP.net:

由 PHP.net 提供:

class User {
    const GIVEN = 1;  // class constants can't be labeled static nor assigned visibility
    public $a=2;
    public static $b=3;

    public function me(){
        echo "print me";
    }
     public static function you() {
        echo "print you";
    }
}

class myUser extends User {
}

// Are properties and methods instantiated to an object of a class, & are they accessible?
//$object1= new User();        // uncomment this line with each of the following lines individually
//echo $object1->GIVEN . "</br>";        // yields nothing
//echo $object1->GIVE . "</br>";        //  deliberately misnamed, still yields nothing
//echo $object1->User::GIVEN . "</br>";    // yields nothing
//echo $object1->a . "</br>";        // yields 2
//echo $object1->b . "</br>";        // yields nothing
//echo $object1->me() . "</br>";        // yields print me
//echo $object1->you() . "</br>";        // yields print you

// Are  properties and methods instantiated to an object of a child class,  & are accessible?
//$object2= new myUser();        // uncomment this line with each of the following lines individually
//echo $object2->GIVEN . "</br>";        // yields nothing
//echo $object2->a . "</br>";        // yields 2
//echo $object2->b . "</br>";        // yields nothing
//echo $object2->me() . "</br>";        // yields print me
//echo $object2->you() . "</br>";        // yields print you

// Are the properties and methods accessible directly in the class?
//echo User::GIVEN . "</br>";        // yields 1
//echo User::$a . "</br>";            // yields fatal error since it is not static
//echo User::$b . "</br>";            // yields 3
//echo User::me() . "</br>";        // yields print me
//echo User::you() . "</br>";        // yields print you

// Are the properties and methods copied to the child class and are they accessible?
//echo myUser::GIVEN . "</br>";        // yields 1
//echo myUser::$a . "</br>";        // yields fatal error since it is not static
//echo myUser::$b . "</br>";        // yields 3
//echo myUser::me() . "</br>";        // yields print me
//echo myUser::you() . "</br>";        // yields print you
?>

回答by hakre

This is PHP 4 backwards compatibility. In PHP 4 you could not differ between an object method and the global function written as a static class method. Therefore both did work.

这是 PHP 4 的向后兼容性。在 PHP 4 中,对象方法和编写为静态类方法的全局函数没有区别。因此两者都有效。

However with the changes in the object model with PHP 5 - http://php.net/oop5- the static keyword has been introduced.

然而,随着 PHP 5 对象模型的变化 - http://php.net/oop5- 引入了 static 关键字。

And then since PHP 5.1.3 you get proper strict standard warnings about those like:

然后从 PHP 5.1.3 开始,您会收到有关以下内容的适当严格的标准警告:

Strict Standards: Non-static method Foo::bar() should not be called statically

严格标准:非静态方法 Foo::bar() 不应静态调用

And/Or:

和/或:

Strict Standards: Non-static method Foo::bar() should not be called statically, assuming $this from incompatible context

严格标准:非静态方法 Foo::bar() 不应静态调用,假设 $this 来自不兼容的上下文

which you should have enabled for your development setup. So it's merely backwards compatibility to a time where the language couldn't differ enough so this was "defined" at run-time.

您应该为您的开发设置启用。所以它只是向后兼容,因为语言不能有足够的差异,所以这是在运行时“定义”的。

Nowadays you can define it already in the code, however the code will not break if you still call it "wrong".

现在你可以在代码中定义它,但是如果你仍然称它为“错误”,代码不会中断。

Some Demo to trigger the error messages and to show the changed behavior over different PHP versions: http://3v4l.org/8WRQH

一些 Demo 触发错误消息并显示不同 PHP 版本的更改行为:http: //3v4l.org/8WRQH

回答by webbiedave

PHP 4 did not have a static keyword (in function declaration context) but still allowed methods to be called statically with ::. This continued in PHP 5 for backwards compatibility purposes.

PHP 4 没有 static 关键字(在函数声明上下文中),但仍然允许使用::. 出于向后兼容性的目的,这在 PHP 5 中继续。

回答by Malus Jan

Warning In PHP 7, calling non-static methods statically is deprecated, and will generate an E_DEPRECATED warning. Support for calling non-static methods statically may be removed in the future.

警告 在 PHP 7 中,不推荐使用静态调用非静态方法,并将生成 E_DEPRECATED 警告。将来可能会删除对静态调用非静态方法的支持。

Link

关联

回答by Jake N

You can do this, but your code will error if you use $thisin the function called fun1()

你可以这样做,但如果你$this在调用的函数中使用你的代码会出错fun1()

回答by Jacob Relkin

In most languages you will need to have an instance of the class in order to perform instance methods. It appears that PHP will create a temporary instance when you call an instance method with the scope resolution operator.

在大多数语言中,您需要有一个类的实例才能执行实例方法。当您使用范围解析运算符调用实例方法时,PHP 似乎会创建一个临时实例。

回答by brian_d

Not sure why PHP allows this, but you do not want to get into the habit of doing it. Your example only works because it does not try to access non-static properties of the class.

不知道为什么 PHP 允许这样做,但您不想养成这样做的习惯。您的示例之所以有效,是因为它不会尝试访问类的非静态属性。

Something as simple as:

像这样简单的事情:

<?php
class Foo {

    private $color;

    public function bar() {
        echo 'before';
        $this->color = "blue";
        echo 'after';
    }
}

Foo::bar();

would result in a fatal error

会导致致命错误

回答by bpile

I have noticed that if you call non-static method self::test() from within a class, no warning for strict standard will be issued, like when you call Class::test(). I believe that this is not related to LSB, since my class was not extended (tested on php 5.5)?

我注意到,如果您从类中调用非静态方法 self::test(),则不会发出严格标准的警告,就像您调用 Class::test() 时一样。我相信这与 LSB 无关,因为我的课程没有扩展(在 php 5.5 上测试)?