Вызов нестатического метода с двойной колонкой (: :)

Почему я не могу использовать метод нестатический с синтаксисом методов 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 

PHP очень свободен со статическими и нестационарными методами. Одна вещь, которую я не вижу здесь, заключается в том, что если вы вызываете нестатический метод, ns статически из нестатического метода класса C , $this внутри ns будет ссылаться на ваш экземпляр 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 

На самом деле это ошибка, если у вас строгая отчетность об ошибках, но не иначе.

Это известная «причуда» PHP. По замыслу предотвращать обратное распространение для выяснения, если какое-то время назад мы фактически создали объект или нет (помните, PHP интерпретируется, а не компилируется). Тем не менее, при доступе к любому нестационарному члену оператор разрешения с помощью разрешающей способности, если объект не создан, будет выдавать фатальную ошибку.

Предоставлено 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 ?> 

PHP 4 не имел статического ключевого слова (в контексте объявления функции), но все же разрешил методы называть статически с :: . Это продолжалось в PHP 5 для обратной совместимости.

Это обратная совместимость PHP 4. В PHP 4 вы не можете различать метод объекта и глобальную функцию, написанную как метод статического класса. Поэтому оба работали.

Однако с изменениями в объектной модели с PHP 5 – http://php.net/oop5 – введено статическое ключевое слово.

И тогда, начиная с PHP 5.1.3, вы получаете правильные строгие стандартные предупреждения о таких, как:

Строгие стандарты: нестатический метод Foo :: bar () не следует называть статически

И / Или:

Строгие стандарты: нестатический метод Foo :: bar () не следует называть статически, предполагая $ this из несовместимого контекста

которые вы должны включить для своей разработки. Таким образом, это просто обратная совместимость со временем, когда язык не может быть достаточно разным, поэтому он был «определен» во время выполнения.

В настоящее время вы можете определить его уже в коде, однако код не сломается, если вы все еще называете его «неправильным».

Некоторая демонстрация для запуска сообщений об ошибках и отображения измененного поведения в разных версиях PHP: http://3v4l.org/8WRQH

Вы можете это сделать, но ваш код будет ошибочным, если вы используете $this в функции fun1()

На большинстве языков вам понадобится экземпляр класса для выполнения методов экземпляра. Похоже, что PHP создаст временный экземпляр, когда вы вызываете метод экземпляра с оператором разрешения области.

Не уверен, почему PHP это позволяет, но вы не хотите привыкать делать это. Ваш пример работает только потому, что он не пытается получить доступ к нестационарным свойствам класса.

Что-то простое:

 <?php class Foo { private $color; public function bar() { echo 'before'; $this->color = "blue"; echo 'after'; } } Foo::bar(); 

приведет к фатальной ошибке

Я заметил, что если вы вызовете нестатический метод self :: test () из класса, не будет выдано предупреждение о строгом стандарте, например, когда вы вызываете Class :: test (). Я считаю, что это не связано с LSB, так как мой класс не был расширен (проверен на php 5.5)?

Предупреждение. В PHP 7 вызов статических методов статически устарел и будет генерировать предупреждение E_DEPRECATED. Поддержка вызова нестатических методов статически может быть удалена в будущем.

Ссылка