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

class t {
    public function tt()
    {
        echo 1;
    }
}
t::tt();

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

6 ответов


кроме того, если вы попытаетесь использовать $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 позволяет вам что-то делать (возможно по историческим причинам-как совместимость со старыми версиями), это не значит, что вы должны сделать это !


на Ключевое Слово Static

Так как статические методы вызываются без создания экземпляра созданного объекта, псевдо-переменная $This не доступна внутри метода, объявленного как static.

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

вызов нестатических методов статически генерирует предупреждение уровня 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();

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


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

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


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


да, критическая разница заключается в том, что методы, объявленные static не имеют доступа к переменной object-context,$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 все равно вызовет фатальную ошибку и выйдет из программы.


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

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