php - para - ¿Cuándo usar uno mismo sobre $ esto?
lista de etiquetas php (22)
Este es un ejemplo del uso correcto de $ this y self para variables miembro no estáticas y estáticas:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo $this->non_static_member . '' ''
. self::$static_member;
}
}
new X();
?>
En PHP 5, ¿cuál es la diferencia entre usar self
y $this
?
¿Cuándo es apropiado cada uno?
Respuesta corta
Use
$this
para referirse al objeto actual. Useself
para referirse a la clase actual. En otras palabras, use$this->member
para$this->member
no estáticos, useself::$member
para miembros estáticos.
Respuesta completa
Este es un ejemplo del uso correcto de $this
y self
para variables miembro no estáticas y estáticas:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo $this->non_static_member . '' ''
. self::$static_member;
}
}
new X();
?>
Este es un ejemplo de uso incorrecto de $this
y self
para variables miembro no estáticas y estáticas:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo self::$non_static_member . '' ''
. $this->static_member;
}
}
new X();
?>
Aquí hay un ejemplo de polimorfismo con $this
para funciones miembro:
<?php
class X {
function foo() {
echo ''X::foo()'';
}
function bar() {
$this->foo();
}
}
class Y extends X {
function foo() {
echo ''Y::foo()'';
}
}
$x = new Y();
$x->bar();
?>
Este es un ejemplo de supresión del comportamiento polimórfico mediante el uso de self
para funciones miembro:
<?php
class X {
function foo() {
echo ''X::foo()'';
}
function bar() {
self::foo();
}
}
class Y extends X {
function foo() {
echo ''Y::foo()'';
}
}
$x = new Y();
$x->bar();
?>
La idea es que
$this->foo()
llama a la función miembrofoo()
de cualquier tipo que sea el tipo exacto del objeto actual. Si el objeto es detype X
, entonces llama aX::foo()
. Si el objeto es detype Y
, llama aY::foo()
. Pero con self :: foo (),X::foo()
siempre se llama.
De http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Por http://board.phpbuilder.com/member.php?145249-laserlight
Como nadie aquí habló sobre actuaciones, aquí hay un pequeño punto de referencia que hice (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
Esos son los resultados de 2 000 000 carreras, y aquí está el código que usé:
<?php
require ''../vendor/autoload.php'';
// My small class to do benchmarks
// All it does is looping over every test x times and record the
// time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb/Benchmark/Benchmark(2000000);
class Foo
{
public function calling_this()
{
$this->called();
}
public function calling_self()
{
self::called();
}
public function calling_static()
{
static::called();
}
public static function called()
{
}
}
$b->add(''$this->'', function () { $foo = new Foo; $foo->calling_this(); });
$b->add(''self::'', function () { $foo = new Foo; $foo->calling_self(); });
$b->add(''static::'', function () { $foo = new Foo; $foo->calling_static(); });
$b->run();
Creo que la pregunta no era si puede llamar al miembro estático de la clase llamando a ClassName::staticMember
. La pregunta era cuál es la diferencia entre usar self::classmember
y $this->classmember
.
Por ejemplo, los dos ejemplos siguientes funcionan sin errores, ya sea que uses self::
o $this->
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
$this->name = $new_name;
$this->address = $new_address;
}
}
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
self::$name = $new_name;
self::$address = $new_address;
}
}
De esta entrada de blog :
self
refiere a la clase actualself
puede utilizarse para llamar a funciones estáticas y hacer referencia a variables miembro estáticasself
puede ser usado dentro de funciones estáticasself
también puede desactivar el comportamiento polimórfico al pasar por alto el vtable$this
refiere al objeto actual$this
puede ser usado para llamar a funciones estáticas.$this
no debe usarse para llamar a variables miembro estáticas. Use elself
enself
lugar.$this
no puede ser usado dentro de funciones estáticas.
Dentro de una definición de clase, $ se refiere al objeto actual, mientras que self se refiere a la clase actual.
Es necesario referirse a un elemento de clase usando self, y referirse a un elemento de objeto usando $ this.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
En PHP, utiliza la palabra clave self para acceder a métodos y propiedades estáticas.
El problema es que puedes reemplazar $this->method()
con self::method()
cualquier lugar, sin importar si el method()
está declarado estático o no. Entonces, ¿cuál debería usar?
Considere este código:
class ParentClass {
function test() {
self::who(); // will output ''parent''
$this->who(); // will output ''child''
}
function who() {
echo ''parent'';
}
}
class ChildClass extends ParentClass {
function who() {
echo ''child'';
}
}
$obj = new ChildClass();
$obj->test();
En este ejemplo, self::who()
siempre generará ''padre'', mientras que $this->who()
dependerá de la clase que tenga el objeto.
Ahora podemos ver que self se refiere a la clase en la que se llama, mientras que $this
refiere a la clase del objeto actual .
Por lo tanto, debe usar self solo cuando $this
no está disponible, o cuando no quiere permitir que las clases descendientes sobrescriban el método actual.
La palabra clave self NO se refiere simplemente a la ''clase actual'', al menos no de una manera que lo restringe a miembros estáticos. En el contexto de un miembro no estático, self
también proporciona una forma de omitir vtable ( vea wiki en vtable ) para el objeto actual. Del mismo modo que puede usar parent::methodName()
para llamar a la versión de los padres de una función, también puede llamar a self::methodName()
para llamar a la implementación de clases actual de un método.
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getTitle() {
return $this->getName()." the person";
}
public function sayHello() {
echo "Hello, I''m ".$this->getTitle()."<br/>";
}
public function sayGoodbye() {
echo "Goodbye from ".self::getTitle()."<br/>";
}
}
class Geek extends Person {
public function __construct($name) {
parent::__construct($name);
}
public function getTitle() {
return $this->getName()." the geek";
}
}
$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();
Esto dará como resultado:
Hola soy luis el friki
Adiós de ludwig la persona
sayHello()
usa el puntero $this
, por lo que se invoca vtable para llamar a Geek::getTitle()
. sayGoodbye()
usa self::getTitle()
, por lo que no se usa vtable, y se llama Person::getTitle()
. En ambos casos, estamos tratando con el método de un objeto instanciado y tenemos acceso al puntero $this
dentro de las funciones llamadas.
Para entender realmente de qué estamos hablando cuando hablamos de self
contra $this
, necesitamos profundizar en lo que está sucediendo a un nivel conceptual y práctico. Realmente no siento que ninguna de las respuestas haga esto apropiadamente, así que aquí está mi intento.
Comencemos hablando de lo que es una clase y un objeto .
Clases y objetos, conceptualmente
Entonces, ¿qué es una clase ? Mucha gente lo define como un plano o una plantilla para un objeto. De hecho, puedes leer más sobre las clases en PHP aquí . Y hasta cierto punto, eso es lo que realmente es. Veamos una clase:
class Person {
public $name = ''my name'';
public function sayHello() {
echo "Hello";
}
}
Como puede ver, hay una propiedad en esa clase llamada $name
y un método (función) llamado sayHello()
.
Es muy importante tener en cuenta que la clase es una estructura estática. Lo que significa que la Person
la clase, una vez definida, es siempre la misma en todas partes que la miras.
Por otro lado, un objeto es lo que se llama una instancia de una Clase. Lo que eso significa es que tomamos el "plano" de la clase y lo usamos para hacer una copia dinámica. Esta copia ahora está vinculada específicamente a la variable en la que está almacenada. Por lo tanto, cualquier cambio en una instancia es local a esa instancia.
$bob = new Person;
$adam = new Person;
$bob->name = ''Bob'';
echo $adam->name; // "my name"
Creamos nuevas instancias de una clase usando el new
operador.
Por lo tanto, decimos que una Clase es una estructura global, y un Objeto es una estructura local. No te preocupes por esa graciosa ->
sintaxis, vamos a entrar en eso en un momento.
Otra cosa de la que deberíamos hablar es que podemos comprobar si una instancia es una instanceof
una clase en particular: $bob instanceof Person
que devuelve un valor booleano si la instancia $bob
se creó con la clase Person
o un hijo de Person
.
Definiendo estado
Así que vamos a profundizar en lo que realmente contiene una clase. Hay 5 tipos de "cosas" que una clase contiene:
Propiedades : piense en estas como variables que cada instancia contendrá.
class Foo { public $bar = 1; }
Propiedades estáticas : piense en éstas como variables que se comparten a nivel de clase. Lo que significa que nunca se copian por cada instancia.
class Foo { public static $bar = 1; }
Métodos : son funciones que cada instancia contendrá (y operará en instancias).
class Foo { public function bar() {} }
Métodos estáticos : son funciones que se comparten en toda la clase. No funcionan en instancias, sino en las propiedades estáticas solamente.
class Foo { public static function bar() {} }
Constantes - Constantes resueltas de clase. No profundizar más aquí, pero agregando para completar:
class Foo { const BAR = 1; }
Básicamente, almacenamos información en la clase y en el contenedor de objetos usando "sugerencias" sobre la estática que identifican si la información se comparte (y, por tanto, estática) o no (y, por lo tanto, es dinámica).
Estado y Métodos
Dentro de un método, la instancia de un objeto está representada por la variable $this
. El estado actual de ese objeto está allí, y la mutación (cambio) de cualquier propiedad dará como resultado un cambio en esa instancia (pero no en otras).
Si un método se llama estáticamente, la variable $this
no está definida . Esto se debe a que no hay ninguna instancia asociada con una llamada estática.
Lo interesante aquí es cómo se hacen las llamadas estáticas. Entonces hablemos de cómo accedemos al estado:
Estado de acceso
Así que ahora que hemos almacenado ese estado, necesitamos acceder a él. Esto puede ser un poco complicado (o mucho más que un bit), así que dividamos esto en dos puntos de vista: desde fuera de una instancia / clase (por ejemplo, desde una llamada de función normal, o desde el ámbito global), y dentro de una instancia / class (desde dentro de un método en el objeto).
Desde fuera de una instancia / clase
Desde el exterior de una instancia / clase, nuestras reglas son bastante simples y predecibles. Tenemos dos operadores, y cada uno nos dice inmediatamente si estamos tratando con una instancia o una clase estática:
->
- operador-objeto : siempre se utiliza cuando accedemos a una instancia.$bob = new Person; echo $bob->name;
Es importante tener en cuenta que llamar a
Person->foo
no tiene sentido (ya quePerson
es una clase, no una instancia). Por lo tanto, eso es un error de análisis.::
- scope-resolution-operator : siempre se utiliza para acceder a un método o propiedad estática de Clase.echo Foo::bar()
Además, podemos llamar a un método estático en un objeto de la misma manera:
echo $foo::bar()
Es extremadamente importante tener en cuenta que cuando hacemos esto desde afuera , la instancia del objeto se oculta del método
bar()
. Lo que significa que es exactamente lo mismo que correr:$class = get_class($foo); $class::bar();
Por lo tanto, $this
no está definido en la llamada estática.
Desde el interior de una instancia / clase
Las cosas cambian un poco aquí. Se utilizan los mismos operadores, pero su significado se vuelve significativamente borroso.
El operador de objeto ->
todavía se usa para hacer llamadas al estado de instancia del objeto.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Al llamar al método de la bar()
en $foo
(una instancia de Foo
) utilizando el operador-objeto: $foo->bar()
obtendrá la versión de la instancia de $a
.
Así es como esperamos.
El significado del operador ::
aunque cambia. Depende del contexto de la llamada a la función actual:
Dentro de un contexto estático
Dentro de un contexto estático, cualquier llamada realizada con
::
también será estática. Veamos un ejemplo:class Foo { public function bar() { return Foo::baz(); } public function baz() { return isset($this); } }
Llamar a
Foo::bar()
llamará el métodobaz()
forma estática, y por lo tanto$this
no se rellenará. Vale la pena tener en cuenta que en las versiones recientes de PHP (5.3+) esto provocará un errorE_STRICT
, porque estamos llamando estáticamente a métodos no estáticos.Dentro de un contexto de instancia
Por otro lado, dentro de un contexto de instancia, las llamadas realizadas mediante
::
dependen del receptor de la llamada (el método al que llamamos). Si el método se define comostatic
, utilizará una llamada estática. Si no lo es, reenviará la información de la instancia.Entonces, mirando el código anterior, llamar a
$foo->bar()
devolverátrue
, ya que la llamada "estática" ocurre dentro de un contexto de instancia.
¿Tener sentido? No lo creía. Es confuso.
Palabras clave de atajo
Debido a que unir todo con nombres de clase es bastante sucio, PHP proporciona 3 palabras clave básicas de "atajo" para facilitar la resolución del alcance.
self
- Esto se refiere al nombre de la clase actual. Entoncesself::baz()
es lo mismo queFoo::baz()
dentro de la claseFoo
(cualquier método en él).parent
: se refiere al padre de la clase actual.static
- Esto se refiere a la clase llamada. Gracias a la herencia, las clases secundarias pueden anular métodos y propiedades estáticas. Por lo tanto, llamarlos usandostatic
lugar de un nombre de clase nos permite resolver de dónde proviene la llamada, en lugar del nivel actual.
Ejemplos
La forma más fácil de entender esto es comenzar a ver algunos ejemplos. Vamos a elegir una clase:
class Person {
public static $number = 0;
public $id = 0;
public function __construct() {
self::$number++;
$this->id = self::$number;
}
public $name = "";
public function getName() {
return $this->name;
}
public function getId() {
return $this->id;
}
}
class Child extends Person {
public $age = 0;
public function __construct($age) {
$this->age = $age;
parent::__construct();
}
public function getName() {
return ''child: '' . parent::getName();
}
}
Ahora, también estamos viendo la herencia aquí. Ignore por un momento que este es un modelo de objeto malo, pero veamos qué sucede cuando jugamos con esto:
$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3
Por lo tanto, el contador de ID se comparte entre las dos instancias y los hijos (porque nos estamos usando para acceder a él. Si usamos static
, podríamos anularlo en una clase hijo).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Tenga en cuenta que estamos ejecutando el método de instancia Person::getName()
cada vez. Pero estamos usando parent::getName()
para hacerlo en uno de los casos (el caso secundario). Esto es lo que hace que este enfoque sea poderoso.
Palabra de precaución # 1
Tenga en cuenta que el contexto de llamada es lo que determina si se utiliza una instancia. Por lo tanto:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
No siempre es cierto.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Ahora es muy raro aquí. Estamos llamando a una clase diferente, pero el $this
que se pasa al método Foo::isFoo()
es la instancia de $bar
.
Esto puede causar todo tipo de errores y WTF-ery conceptual. Así que sugiero encarecidamente que evite el ::
operador de los métodos de instancia en cualquier cosa excepto esas tres palabras clave virtuales de "atajo" ( static
, self
y parent
).
Palabra de precaución # 2
Tenga en cuenta que los métodos y propiedades estáticos son compartidos por todos. Eso las hace básicamente variables globales. Con todos los mismos problemas que vienen con los globales. Por lo tanto, estaría realmente indeciso a almacenar información en métodos / propiedades estáticas a menos que esté cómodo con que sea verdaderamente global.
Palabra de precaución # 3
En general, querrá usar lo que se conoce como vinculación estática tardía mediante el uso de static
lugar de self
. Pero tenga en cuenta que no son lo mismo, por lo que decir "siempre usar static
lugar de self
es realmente miope. En su lugar, deténgase y piense en la llamada que desea hacer y piense si quiere que las clases secundarias puedan anular esa llamada. llamada estática resuelta .
TL / DR
Lástima, vuelve atrás y léelo. Puede ser demasiado largo, pero es tan largo porque este es un tema complejo
TL / DR # 2
Está bien. En resumen, self
se usa para hacer referencia al nombre de la clase actual dentro de una clase, donde como $this
refiere a la instancia del objeto actual. Tenga en cuenta que self
es un atajo de copiar / pegar. Puede reemplazarlo de manera segura con el nombre de su clase, y funcionará bien. Pero $this
es una variable dinámica que no se puede determinar de antemano (y puede que ni siquiera sea su clase).
TL / DR # 3
Si se utiliza el operador de objeto ( ->
), entonces siempre se sabe que se trata de una instancia. Si se usa el operador de resolución de alcance ( ::
, necesita más información sobre el contexto (¿ya estamos en un contexto de objeto? ¿Estamos fuera de un objeto? Etc.).
Según http://www.php.net/manual/en/language.oop5.static.php no hay $self
. Solo hay $this
, para referirse a la instancia actual de la clase (el objeto), y self, que puede usarse para referirse a miembros estáticos de una clase. La diferencia entre una instancia de objeto y una clase entra en juego aquí.
$this->
se usa para referirse a una instancia específica de las variables de una clase (variables miembro) o métodos.
Example:
$derek = new Person();
$ derek es ahora una instancia específica de Person. Cada persona tiene un primer nombre y un último nombre, pero $ derek tiene un primer nombre y un apellido (Derek Martin) específicos. Dentro de la instancia de $ derek, podemos referirnos a ellos como $ this-> first_name y $ this-> last_name
ClassName :: se usa para referirse a ese tipo de clase, y sus variables estáticas, métodos estáticos. Si ayuda, puedes reemplazar mentalmente la palabra "estática" por "compartida". Debido a que se comparten, no pueden referirse a $ this, que se refiere a una instancia específica (no compartida). Las variables estáticas (es decir, $ db_connection estática) se pueden compartir entre todas las instancias de un tipo de objeto. Por ejemplo, todos los objetos de la base de datos comparten una sola conexión ($ estática de conexión).
Variables estáticas Ejemplo: Pretenda que tenemos una clase de base de datos con una única variable miembro: static $ num_connections; Ahora, pon esto en el constructor:
function __construct()
{
if(!isset $num_connections || $num_connections==null)
{
$num_connections=0;
}
else
{
$num_connections++;
}
}
Al igual que los objetos tienen constructores, también tienen destructores, que se ejecutan cuando el objeto muere o no está configurado:
function __destruct()
{
$num_connections--;
}
Cada vez que creamos una nueva instancia, aumentará nuestro contador de conexión en uno. Cada vez que destruyamos o dejemos de usar una instancia, disminuirá el contador de conexión en uno. De esta manera, podemos monitorear la cantidad de instancias del objeto de base de datos que tenemos en uso con:
echo DB::num_connections;
Debido a que $ num_connections es estático (compartido), reflejará el número total de objetos de base de datos activos. Es posible que haya visto esta técnica utilizada para compartir conexiones de base de datos entre todas las instancias de una clase de base de datos. Esto se hace porque la creación de la conexión de la base de datos lleva mucho tiempo, por lo que es mejor crear solo una y compartirla (esto se denomina patrón Singleton).
Los métodos estáticos (es decir, la vista estática pública :: format_phone_number ($ dígitos)) se pueden usar SIN la primera instancia de uno de esos objetos (es decir, no se refieren internamente a $ this).
Ejemplo de método estático:
public static function prettyName($first_name, $last_name)
{
echo ucfirst($first_name).'' ''.ucfirst($last_name);
}
echo Person::prettyName($derek->first_name, $derek->last_name);
Como puede ver, la función estática pública prettyName no sabe nada sobre el objeto. Simplemente funciona con los parámetros que se pasan, como una función normal que no forma parte de un objeto. ¿Por qué molestarse, entonces, si no pudiéramos tenerlo como parte del objeto?
- Primero, adjuntar funciones a objetos le ayuda a mantener las cosas organizadas, para que sepa dónde encontrarlas.
- En segundo lugar, evita conflictos de nombres. En un proyecto grande, es probable que dos desarrolladores creen funciones getName (). Si uno crea un ClassName1 :: getName (), y el otro crea ClassName2 :: getName (), no hay ningún problema. No conflicto. ¡Yay métodos estáticos!
SELF :: Si está codificando fuera del objeto que tiene el método estático al que desea referirse, debe llamarlo usando el nombre del objeto View :: format_phone_number ($ phone_number); Si está codificando dentro del objeto que tiene el método estático al que desea referirse, puede usar el nombre del objeto View :: format_phone_number ($ pn), O puede usar el atajo self :: format_phone_number ($ pn)
Lo mismo ocurre con las variables estáticas: Ejemplo: Ver :: templates_path versus self :: templates_path
Dentro de la clase DB, si nos estuviéramos refiriendo a un método estático de algún otro objeto, usaríamos el nombre del objeto: Ejemplo: Session :: getUsersOnline ();
Pero si la clase DB quisiera referirse a su propia variable estática, solo diría self: Ejemplo: self :: connection;
Espero que ayude a aclarar las cosas :)
$this
se refiere al objeto de clase actual, se self
refiere a la clase actual (objeto no). La clase es el plano del objeto. Así que definas una clase, pero construyes objetos.
Así que en otras palabras, usar self for static
y this for none-static members or methods
.
también en el escenario hijo / padre self / parent
se utiliza principalmente para identificar miembros y métodos de clase de padres e hijos.
self
(no $ self) se refiere al tipo de clase, donde como $this
refiere a la instancia actual de la clase. self
es para uso en funciones miembro estáticas para permitirle acceder a variables miembro estáticas. $this
se usa en funciones miembro no estáticas, y es una referencia a la instancia de la clase en la que se llamó la función miembro.
Como this
es un objeto, lo usas como: $this->member
Debido a que self
no es un objeto, es básicamente un tipo que se refiere automáticamente a la clase actual, se usa como: self::member
self
refiere a la clase actual (en la que se llama),
$this
refiere al objeto actual. Puedes usar estática en lugar de auto. Vea el ejemplo:
class ParentClass {
function test() {
self::which(); // output ''parent''
$this->which(); // output ''child''
}
function which() {
echo ''parent'';
}
}
class ChildClass extends ParentClass {
function which() {
echo ''child'';
}
}
$obj = new ChildClass();
$obj->test();
Salida: padre hijo
NO UTILICE self::
, use static::
Hay otro aspecto del yo que vale la pena mencionar. Annoyingly self::
refiere al alcance en el punto de definición y no en el punto de ejecución . Considera esta clase simple con dos métodos:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
Si llamamos a Person::status()
veremos "La persona está viva". Ahora considera lo que sucede cuando hacemos una clase que hereda de esto:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Llamando a Deceased::status()
esperaríamos ver "La persona falleció", sin embargo, lo que vemos es "La persona está viva", ya que el alcance contiene la definición del método original cuando se definió la llamada a self::getStatus()
.
PHP 5.3 tiene una solución. el operador static::
resolution implementa "enlace estático tardío", que es una forma elegante de decir que está vinculado al alcance de la clase llamada. Cambie la línea en status()
a static::getStatus()
y los resultados son los que esperaría. En versiones anteriores de PHP, tendrá que encontrar un kludge para hacer esto.
Así que para responder a la pregunta no como se pregunta ...
$this->
refiere al objeto actual (una instancia de una clase), mientras que static::
refiere a una clase
Me encontré con la misma pregunta y la respuesta simple es:
- $ Esto requiere una instancia de la clase.
- self :: does
Siempre que utilice métodos estáticos o atributos estáticos y desee llamarlos sin tener un objeto de la clase instanciada, debe usar self :: para llamarlos, porque $ esto siempre requiere que se cree un objeto.
Úselo self
si desea llamar a un método de una clase sin crear un objeto / instancia de esa clase, y así ahorrar RAM (a veces usar el self para ese propósito). En otras palabras, en realidad está llamando a un método estáticamente. Utilizar this
para la perspectiva del objeto.
Adicionalmente ya que $this::
no se ha discutido aún.
Solo con fines informativos, a partir de PHP 5.3 al tratar con objetos instanciados para obtener el valor de alcance actual, en lugar de usar static::
, alternativamente se puede usar $this::
como tal.
class Foo
{
const NAME = ''Foo'';
//Always Foo::NAME (Foo) due to self
protected static $staticName = self::NAME;
public function __construct()
{
echo $this::NAME;
}
public function getStaticName()
{
echo $this::$staticName;
}
}
class Bar extends Foo
{
const NAME = ''FooBar'';
/**
* override getStaticName to output Bar::NAME
*/
public function getStaticName()
{
$this::$staticName = $this::NAME;
parent::getStaticName();
}
}
$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar
Usar el código anterior no es una práctica común o recomendada, sino simplemente para ilustrar su uso, y es actuar como un "¿Sabías?" en referencia a la pregunta del cartel original.
También representa el uso de, $object::CONSTANT
por ejemplo echo $foo::NAME;
, en contraposición a$this::NAME;
Caso 1: El uso self
puede usarse para constantes de clase
class classA { const FIXED_NUMBER = 4; self::POUNDS_TO_KILOGRAMS }
Si desea llamarlo fuera de la clase, use classA::POUNDS_TO_KILOGRAMS
para acceder a las constantes
Caso 2: Para propiedades estáticas
class classC { public function __construct() { self::$_counter++; $this->num = self::$_counter; } }
Cuando self
se usa con el ::
operador, se refiere a la clase actual, que se puede hacer tanto en contextos estáticos como no estáticos. $this
se refiere al objeto en sí. Además, es perfectamente legal usarlo $this
para llamar a métodos estáticos (pero no para referirse a campos).
De acuerdo con php.net hay tres palabras clave especiales en este contexto: self
, parent
y static
. Se utilizan para acceder a propiedades o métodos desde dentro de la definición de clase.
$this
, por otro lado, se utiliza para llamar a una instancia y métodos de cualquier clase siempre y cuando esa clase sea accesible.
- El puntero del objeto $ esto se refiere al objeto actual.
- El valor de la clase "estático" se refiere al objeto actual.
- El valor de clase "self" se refiere a la clase exacta en la que se definió.
- El valor de clase "padre" se refiere al padre de la clase exacta en la que se definió.
Vea el siguiente ejemplo que muestra la sobrecarga.
<?php
class A {
public static function newStaticClass()
{
return new static;
}
public static function newSelfClass()
{
return new self;
}
public function newThisClass()
{
return new $this;
}
}
class B extends A
{
public function newParentClass()
{
return new parent;
}
}
$b = new B;
var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A
class C extends B
{
public static function newSelfClass()
{
return new self;
}
}
$c = new C;
var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"
La mayoría de las veces desea referirse a la clase actual por lo que usa static
o $this
. Sin embargo, hay ocasiones en las que necesitas self
porque quieres la clase original independientemente de lo que la extienda. (Muy, muy rara vez)