class t { public function tt() { echo 1; } } t::tt();
См.? Нестатическая функция также может быть вызвана на уровне класса. Так что же изменится, если я добавлю static
ключевое слово перед public
?
Кроме того, если вы попытаетесь использовать $this
в своем методе, например:
class t { protected $a = 10; public function tt() { echo $this->a; echo 1; } } t::tt();
Вы получите Fatal Error при вызове нестатического метода статически:
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
Итак: не так хорошо 😉
Тем не менее статический вызов нестатического метода не похож на какую-либо хорошую практику (вероятно, поэтому он вызывает предупреждение Strict) , поскольку статические методы не имеют того же значения, что и нестатические: статические методы делают не ссылаться на какой-либо объект, в то время как нестатические методы работают над экземпляром вызываемого класса.
Еще раз: даже если PHP позволяет вам что-то сделать (возможно, по историческим причинам – например, совместимость со старыми версиями) , это не значит, что вы должны это сделать!
Статическое ключевое слово
Поскольку статические методы вызываются без экземпляра созданного объекта, псевдопеременная $ this недоступна внутри метода, объявленного как статический.
Статические свойства не могут быть доступны через объект с помощью оператора стрелки ->.
Вызов нестатических методов статически генерирует предупреждение уровня E_STRICT.
Просто потому, что вы можете вызывать нестатические методы статически, это не значит, что вы должны. Это плохая форма.
Обычно статический метод также называется методом класса, а нестатический метод также называется методом объекта или методом экземпляра .
Разница между методом класса и объектным методом заключается в том, что методы класса могут обращаться только к свойствам класса (статические свойства), тогда как объектные методы используются для доступа к свойствам объекта (свойства одного и того же экземпляра класса).
Статические методы и свойства используются для совместного использования общих данных или для всех экземпляров этого конкретного класса.
Например, вы можете использовать статическое свойство для отслеживания количества экземпляров:
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();
с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();
Обратите внимание, что статический счетчик свойств является закрытым, поэтому доступ к нему может получить только сам класс и экземпляры этого класса, но не извне.
Основное отличие, которое не упоминалось, относится к полиморфному поведению .
Нестационарные методы при переопределении в производном классе переопределяют метод базового класса и допускают полиморфное поведение, основанное на типе экземпляра, на который они вызваны. Это не относится к статическим методам .
PHP 5.3 представил концепцию поздней статической привязки, которая может использоваться для ссылки на вызываемый класс в контексте статического наследования.
Да, критическая разница заключается в том, что методы, объявленные static
, не имеют доступа к переменной object-context, $this
.
Кроме того, вызов нестатического метода, если не в контексте объекта, вызывает E_STRICT
ошибки 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
все равно вызовет фатальную ошибку и выйдет из программы.
Помимо синтаксиса и функциональных различий существует также разница в производительности.
Вы можете обратиться к этому более или менее детальному сравнению статических и нестатических методов в PHP .