Статический член PHP и член экземпляра не отличаются. Почему PHP делает это (без предупреждения)? - PullRequest
4 голосов
/ 19 апреля 2011
<?php
class A {
  public function instanceFunc() {
    echo "instance";
  }

  public static function staticFunc() {
    echo "static";
  }
}

A::instanceFunc(); // instance
$a = new A();
$a->staticFunc(); // static

Это означает, что в PHP статический метод и метод экземпляра не имеют различий вообще.Zend даже не жалуется на это (БЕЗ ПРЕДУПРЕЖДЕНИЯ).

В Zend Engine.и статический метод, и метод экземпляра, все они сохранены в zend_class_entry.function_table.

Почему PHP ведет себя так?Это ошибка или особенность?

Ответы [ 3 ]

3 голосов
/ 19 апреля 2011

Это потенциальная копия Имеет ли статический метод в PHP какую-либо разницу с нестатическим методом? .

Если вы включите предупреждения E_STRICT, в противном случае вы получите сообщение об ошибке, в противном случаеВы можете беззвучно вызывать нестатический метод, как если бы он был статическим.Как упомянуто в ответах здесь и на другом вопросе, реальный статический / нестатический метод не достиг бы большого успеха без доступа к $this или self, как это было написано, чтобы ожидать.

См.документы: http://www.php.net/manual/en/language.oop5.static.php

Вот с чем поиграть:

http://codepad.org/Gbu9T6Zv

2 голосов
/ 19 апреля 2011

Если вы попытаетесь запустить приведенный ниже код и посмотреть на вывод обратной трассировки, вы увидите, что PHP преобразует instanceFunc () в статический метод при вызове в статическом контексте.Однако в контексте экземпляра он будет обрабатывать его как вызов экземпляра.

Если вы добавляете в экземпляр переменные экземпляра (удаляете закомментированные строки), то при вызове instanceFunc () из статического вызова возникает фатальная ошибка.

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

Что касается staticFunc (), оба вызова показывают, что PHP интерпретирует их как статические вызовы, что и следовало ожидать.

class A {
  private $x = 5;
  private $y = 6;
  private $z;
  public function instanceFunc() {
    //$this->z = $this->y * $this->x;
    //echo $this->z;
    var_dump(reset(debug_backtrace()));
  }

  public static function staticFunc() {
    var_dump(reset(debug_backtrace()));
  }
}
$a = new A();
A::instanceFunc(); // static call of intended instance method
$a->instanceFunc(); // instance call of instance method
A::staticFunc();
$a->staticFunc();

Пример вывода (код работает с комментариями):

array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(19) ["function"]=>  string(12) "instanceFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=>  array(0) { } } 
array(7) { ["file"]=> string(59) "test.php" ["line"]=> int(22) ["function"]=> string(12) "instanceFunc" ["class"]=> string(1) "A" ["object"]=> object(A)#8 (3) { ["x:private"]=> int(5) ["y:private"]=> int(6) ["z:private"]=> NULL } ["type"]=> string(2) "->" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(24) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(26) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } }
1 голос
/ 19 апреля 2011

Я не уверен, почему бы не выдать предупреждение или хотя бы ошибку. Тем не менее, есть некоторые основные различия в статических и экземплярах. Статический метод не может использовать переменные класса, которые не являются статическими. Что легко проверить, добавив нестатическую открытую / закрытую переменную и попытавшись отобразить ее в staticFunc, что приведет к ошибке.

Я думаю, что главная цель - понять разницу между ними и как правильно их использовать. Что касается того, почему PHP по крайней мере не создает Уведомление, я не знаю, возможно, это связано с его непринужденной природой. Мне интересен ответ, который может дать кто-то, кто имеет больше знаний об этом, это своего рода дополнительная информация.

Я протестировал его с полным сообщением об ошибках, и, конечно же, он действительно не выдает уведомление или предупреждение.


UPDATE

При некотором тестировании кажется, что, когда вы вызываете неотмеченную статическую функцию как статическую функцию, вы все равно не можете использовать закрытые / публичные переменные. Что для нормальных функций, скорее всего, приведет к их ошибкам. Именно поэтому ошибка или уведомление никогда не появлялись. Тем не менее, было бы неплохо, чтобы он что-то об этом сказал, поскольку использование неназначенной статической функции таким образом, безусловно, нехорошо.

...