2010-03-13 27 views

Respuesta

14

Salvo que, si intenta utilizar $this en su método, de esta manera:

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

que obtendrá un error grave cuando se llama al método no estático estática:

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

es decir, su ejemplo es un poco demasiado simple, y realmente no corresponde a un caso real ;-)


También tenga en cuenta que su ejemplo debe obtener una estricta advertencia (quoting):

llamar a los métodos no estáticos estáticamente genera una advertencia E_STRICT nivel.

Y lo que realmente hace (Por lo menos, con PHP 5.3):

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

Por lo tanto: no tan bueno ;-)


Aún así, llamando estáticamente un no-estático método no se parece a ningún tipo de buena práctica (que es probablemente la razón por la que plantea una advertencia Estricta), ya que los métodos estáticos no tienen el mismo significado que los no estáticos: los métodos estáticos no son importar cualquier objeto, mientras que los métodos no estáticos funcionan en la instancia de la clase a la que se llama.


Una vez más: incluso si PHP le permite hacer algo (Tal vez por razones históricas - como la compatibilidad con versiones anteriores), esto no significa que usted debe hacerlo!

+0

No recibí una advertencia estricta, la configuración de php.ini es 'error_reporting = E_ALL' – user198729

+3

@user: esto es porque' E_ALL' no incluye 'E_STRICT' - ver http://www.php.net/ manual/es/errorfunc.constants.php que indica que 'E_ALL' es *" Todos los errores y advertencias, como se admite, excepto el nivel 'E_STRICT' en PHP <6" * –

+0

Oh, he cambiado a 'error_reporting = E_ALL & E_STRICT', aún sin advertencia ...PHP5.3.0 – user198729

4

El Static Keyword

Debido a métodos estáticos son exigible sin una instancia del objeto creado, la pseudo-variable $ esto no está disponible en el interior del método declarado como estático.

No se puede acceder a las propiedades estáticas a través del objeto utilizando el operador de flecha ->.

Llamar a métodos no estáticos genera de forma estática un aviso de nivel E_STRICT.

El hecho de que pueda llamar a métodos no estáticos estáticamente no significa que deba hacerlo. Es mala forma.

2

En un método estático en general también se llama método de clase mientras que un método no estático también se llama método de objeto o métodoejemplo. La diferencia entre un método de clase y un método de objeto es que los métodos de clase solo pueden acceder a propiedades de clase (propiedades estáticas) mientras que los métodos de objeto se utilizan para acceder a propiedades

Los métodos y propiedades estáticos se utilizan para compartir datos comunes sobre o para todas las instancias de esa clase específica.

Podría, por ejemplo, utilizar una propiedad estática para realizar un seguimiento del número de instancias:

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(); 

Tenga en cuenta que la propiedad estática contador es privada por lo que sólo se puede acceder por la propia clase e instancias de esa clase pero no desde afuera.

1

Una diferencia principal que no se ha mencionado se relaciona con comportamiento polimórfico.

Los métodos no estáticos, cuando se vuelven a declarar en una clase derivada, anulan el método de clase base y permiten el comportamiento polimórfico en función del tipo de la instancia en la que se invocaron. Este no es el caso de los métodos estáticos.


PHP 5.3 introdujo el concepto de late static binding que puede ser utilizado para hacer referencia a la clase llamada en un contexto de herencia estática.

0

Sí, la diferencia fundamental es que los métodos declarados static no tienen acceso a la variable de contexto de objeto, $this.

Además, la invocación de un método no estático cuando no está en el contexto del objeto provocará un evento de error E_STRICT. Cuando está habilitado, el comportamiento predeterminado de ese evento es enviar un mensaje al registro de errores (o STDERR), pero permitirá que el programa continúe ejecutando.

Además, cualquier intento de referencia $this cuando no se encuentre en un contexto de objeto desencadenará un evento E_ERROR. El comportamiento de ese evento es dar salida a un mensaje en el registro de error (o STDERR) y para salir del programa con el estado 255.

Por ejemplo:

<?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"; 

La salida del anterior es:

========== 
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 

Al cambiar el nivel de informe de error a E_ALL se suprimirán los mensajes de advertencia predeterminados E_STRICT (el evento se seguirá propagando), pero la referencia no válida a $this seguirá causando un error fatal y saldrá del programa.

Cuestiones relacionadas