Есть ли у статического метода в PHP разница с нестатическим методом? - PullRequest
14 голосов
/ 13 марта 2010
class t {
    public function tt()
    {
        echo 1;
    }
}
t::tt();

Видите? Нестатическую функцию также можно вызывать на уровне класса. Так что же будет, если я добавлю ключевое слово static до public?

Ответы [ 6 ]

15 голосов
/ 13 марта 2010

Кроме того, если вы попытаетесь использовать $this в своем методе, например:

class t {
    protected $a = 10;
    public function tt() {
        echo $this->a;
        echo 1;
    }
}
t::tt();

При статическом вызове нестатического метода вы получите фатальную ошибку:

Fatal error: Using $this when not in object context in ...\temp.php on line 11

т.е. ваш пример немного слишком простой и не соответствует реальному случаю; -)


Также обратите внимание, что ваш пример должен получить строгое предупреждение ( цитата ):

Статический вызов нестатических методов генерирует предупреждение уровня E_STRICT.

И это действительно (по крайней мере, с PHP 5.3) :

Strict Standards: Non-static method t::tt() should not be called statically in ...\temp.php on line 12
1

Итак: не очень хорошо; -)


Тем не менее, статический вызов нестатического метода не выглядит хорошей практикой (возможно, именно поэтому он вызывает строгое предупреждение) , поскольку статические методы не имеют того же значения, что и не статические: статические методы не ссылаются ни на один объект, в то время как нестатические методы работают с экземпляром класса, к которому они вызваны.


Еще раз: даже если PHP позволяет вам что-то делать (может быть по историческим причинам - например, совместимость со старыми версиями) , это не значит, что вы должны это делать!

4 голосов
/ 13 марта 2010

Статическое ключевое слово

Поскольку статические методы могут вызываться без экземпляра созданного объекта, псевдопеременная $ this недоступна в методе, объявленном как static.

Статические свойства не могут быть доступны через объект с помощью оператора стрелки ->.

Вызов нестатических методов статически генерирует предупреждение уровня E_STRICT.

То, что вы можете вызывать нестатические методы статически, не означает, что вы должны это делать. Это плохая форма.

2 голосов
/ 13 марта 2010

Как правило, статический метод также называется метод класса , тогда как нестатический метод также называется метод объекта или метод экземпляра .

Разница между методом класса и методом объекта заключается в том, что методы класса могут получать доступ только к свойствам класса (статическим свойствам), тогда как методы объекта используются для доступа к свойствам объекта (свойствам того же самого экземпляра класса).

Статические методы и свойства используются для совместного использования общих данных для или для всех экземпляров этого конкретного класса.

Например, вы можете использовать статическое свойство для отслеживания количества экземпляров:

class A {
    private static $counter = 0;

    public function __construct() {
        self::counter = self::counter + 1;
    }

    public function __destruct() {
        self::counter = self::counter - 1;
    }

    public static function printCounter() {
        echo "There are currently ".self::counter." instances of ".__CLASS__;
    }
}

$a1 = new A();
$a2 = new A();
A::printCounter();
unset($a2);
A::printCounter();

Обратите внимание, что статическое свойство counter является закрытым, поэтому к нему может обращаться только сам класс и экземпляры этого класса, но не извне.

1 голос
/ 12 октября 2011

Основное отличие, которое не было упомянуто, относится к полиморфному поведению .

Нестатические методы, когда они объявлены в производном классе, переопределяют метод базового класса и допускают полиморфное поведение в зависимости от типа экземпляра, к которому они обращаются. Это не относится к статическим методам .


В PHP 5.3 введена концепция позднего статического связывания , которая может использоваться для ссылки на вызываемый класс в контексте статического наследования.

0 голосов
/ 07 мая 2014

Помимо синтаксиса и функциональных различий, существует также разница в производительности.

Вы можете обратиться к этому более или менее подробному сравнению статических и нестатических методов в PHP .

0 голосов
/ 25 марта 2014

Да, критическое различие заключается в том, что объявленные методы static не имеют доступа к переменной контекста объекта, $this.

Кроме того, вызов нестатического метода, когда он не находится в контексте объекта, вызовет событие ошибки E_STRICT. Если этот параметр включен, по умолчанию это событие выводит сообщение в журнал ошибок (или STDERR), но позволяет программе продолжать работу .

Кроме того, любая попытка сослаться на $this, когда он не находится в контексте объекта, вызовет событие E_ERROR. Поведение этого события заключается в выводе сообщения в журнал ошибок (или STDERR) и выходе из программы со статусом 255.

Например:

<?php
error_reporting(-1);
//error_reporting(E_ALL);

class DualNature {
  public static function fnStatic() {
    if ( isset( $this ) ) {
      // never ever gets here
      $myValue = $this->_instanceValue;
    } else {
      // always gets here
      $myValue = self::$_staticValue;
    }
    return $myValue;
  }

  public function fnInstance() {
    if ( isset( $this ) ) {
      // gets here on instance (->) reference only
      $myValue = $this->_instanceValue;
    } else {
      // gets here in all other situations
      $myValue = self::$_staticValue;
    }
    return $myValue;
  }

  public static function fnStaticDeath() {
    return $this->_instanceValue;
  }

  private static $_staticValue = 'no access to $this';
  private $_instanceValue = '$this is available';

}

$thing = new DualNature();
echo "==========\n";
printf("DualNature::fnStatic(): \"%s\"\n", DualNature::fnStatic() );
echo "==========\n";
printf("\$thing::fnStatic(): \"%s\"\n", $thing::fnStatic() );
echo "==========\n";
printf("\$thing->fnStatic(): \"%s\"\n", $thing->fnStatic() );
echo "==========\n";
printf("DualNature::fnInstance(): \"%s\"\n", DualNature::fnInstance() );
echo "==========\n";
printf("\$thing::fnInstance(): \"%s\"\n", $thing::fnInstance() );
echo "==========\n";
printf("\$thing->fnInstance(): \"%s\"\n", $thing->fnInstance() );
echo "==========\n";
printf("\$thing->fnStaticDeath(): \"%s\"\n", $thing->fnStaticDeath() );
echo "==========\n";
echo "I'M ALIVE!!!\n";

Вывод выше:

==========
PHP Strict Standards:  Non-static method DualNature::fnInstance() should not be called statically in example.php on line 45
DualNature::fnStatic(): "no access to $this"
==========
$thing::fnStatic(): "no access to $this"
==========
$thing->fnStatic(): "no access to $this"
PHP Strict Standards:  Non-static method DualNature::fnInstance() should not be called statically in example.php on line 47
==========
DualNature::fnInstance(): "no access to $this"
==========
$thing::fnInstance(): "no access to $this"
==========
$thing->fnInstance(): "$this is available"
==========
PHP Fatal error:  Using $this when not in object context in example.php on line 29

Изменение уровня сообщения об ошибках на E_ALL приведет к подавлению предупреждающих сообщений по умолчанию E_STRICT (событие будет по-прежнему распространяться), но неверная ссылка на $this все равно вызовет фатальную ошибку и выйдет из программы.

...