No PHP 5, qual é a diferença entre usar self
e $this
?
Quando cada um é apropriado?
No PHP 5, qual é a diferença entre usar self
e $this
?
Quando cada um é apropriado?
Respostas:
Use
$this
para se referir ao objeto atual. Useself
para se referir à classe atual. Em outras palavras, use$this->member
para membros não estáticos, useself::$member
para membros estáticos.
Aqui está um exemplo do uso correto de $this
e self
para variáveis de membro não estáticas e 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();
?>
Aqui está um exemplo de uso incorreto de $this
e self
para variáveis de membro não estáticas e 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();
?>
Aqui está um exemplo de polimorfismo com $this
funções-membro:
<?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();
?>
Aqui está um exemplo de suprimir o comportamento polimórfico usando self
para funções de membro:
<?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();
?>
A idéia é que
$this->foo()
chama afoo()
função de membro de qualquer que seja o tipo exato do objeto atual. Se o objeto é detype X
, chama assimX::foo()
. Se o objeto é detype Y
, ele chamaY::foo()
. Mas com self :: foo (),X::foo()
é sempre chamado.
Em http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Por http://board.phpbuilder.com/member.php?145249-laserlight
self
é usado com o operador de resolução do escopo ::
para se referir à classe atual; isso pode ser feito em contextos estáticos e não estáticos. Além disso, é perfeitamente legal usar $this
para chamar métodos estáticos (mas não para referenciar campos).
$this::
?
A palavra-chave self NÃO se refere apenas à 'classe atual', pelo menos não de uma maneira que restrinja você a membros estáticos. Dentro do contexto de um membro não estático, self
também fornece uma maneira de ignorar a vtable ( consulte o wiki na vtable ) para o objeto atual. Assim como você pode usar parent::methodName()
para chamar a versão dos pais de uma função, também pode chamar self::methodName()
para chamar a implementação de classes atual de um 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();
Isso produzirá:
Olá, eu sou Ludwig, o nerd.
Adeus, de Ludwig, a pessoa.
sayHello()
usa o $this
ponteiro, para que a vtable seja chamada para chamar Geek::getTitle()
.
sayGoodbye()
usa self::getTitle()
, portanto, o vtable não é usado e Person::getTitle()
é chamado. Nos dois casos, estamos lidando com o método de um objeto instanciado e temos acesso ao $this
ponteiro nas funções chamadas.
self
está localizado" / "a definição de classe, é uma parte literal de" e também "a classe do objeto" (o que realmente seria static
).
$this::
?
$this::
; todos os casos possíveis já estão cobertos pelas sintaxes mais usadas. Dependendo do que você quer dizer, o uso $this->
, self::
ou static::
.
NÃO USE self::
, usestatic::
Há outro aspecto do eu: que vale a pena mencionar. Irritantemente self::
se refere ao escopo no ponto de definição e não no ponto de execução . Considere esta classe simples com dois métodos:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
Se chamarmos Person::status()
, veremos "A pessoa está viva". Agora considere o que acontece quando criamos uma classe que herda disso:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Ao ligar Deceased::status()
, esperamos ver "A pessoa faleceu", no entanto, o que vemos é "A pessoa está viva", pois o escopo contém a definição do método original ao chamarself::getStatus()
foi definida.
O PHP 5.3 tem uma solução. o static::
operador de resolução implementa "ligação estática tardia", que é uma maneira elegante de dizer que está vinculada ao escopo da classe chamada. Mude a linha status()
para static::getStatus()
e os resultados são o que você esperaria. Nas versões mais antigas do PHP, você terá que encontrar um kludge para fazer isso.
Veja a documentação do PHP
Então, para responder à pergunta não como solicitado ...
$this->
refere-se ao objeto atual (uma instância de uma classe), enquanto static::
refere-se a uma classe
getStatus
método como um que eu chamaria de instância de classe, não de classe.
self::
, pode obtê-lo, menos confusamente, usando o nome específico da classe, por exemplo MyClass::
.
Para realmente entender o que estamos falando quando falamos sobre self
versus $this
, precisamos realmente descobrir o que está acontecendo nos níveis conceitual e prático. Eu realmente não sinto que nenhuma das respostas faça isso adequadamente, então aqui está minha tentativa.
Vamos começar falando sobre o que classe e um objeto .
Então, o que é uma aula ? Muitas pessoas o definem como um modelo ou modelo para um objeto. De fato, você pode ler mais sobre classes no PHP aqui . E até certo ponto é isso que realmente é. Vejamos uma classe:
class Person {
public $name = 'my name';
public function sayHello() {
echo "Hello";
}
}
Como você pode ver, existe uma propriedade nessa classe chamada $name
e um método (função) chamado sayHello()
.
É muito importante observar que a classe é uma estrutura estática. O que significa que a classe Person
, uma vez definida, é sempre a mesma em todos os lugares.
Um objeto, por outro lado, é chamado de instância de uma classe. O que isso significa é que pegamos o "blueprint" da classe e o usamos para fazer uma cópia dinâmica. Agora, esta cópia está vinculada especificamente à variável em que está armazenada. Portanto, qualquer alteração em uma instância é local para ela.
$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"
Criamos novas instâncias de uma classe usando o new
operador
Portanto, dizemos que uma classe é uma estrutura global e um objeto é uma estrutura local. Não se preocupe com essa ->
sintaxe engraçada , vamos abordar isso daqui a pouco.
Outra coisa sobre a qual devemos falar é que podemos verificar se uma instância é uma instanceof
classe específica: $bob instanceof Person
que retorna um booleano se a $bob
instância foi criada usando a Person
classe ou um filho de Person
.
Então, vamos nos aprofundar no que uma classe realmente contém. Existem 5 tipos de "coisas" que uma classe contém:
Propriedades - Pense nelas como variáveis que cada instância conterá.
class Foo {
public $bar = 1;
}
Propriedades estáticas - pense nelas como variáveis compartilhadas no nível da classe. Significando que eles nunca são copiados por cada instância.
class Foo {
public static $bar = 1;
}
Métodos - São funções que cada instância conterá (e operará em instâncias).
class Foo {
public function bar() {}
}
Métodos estáticos - são funções compartilhadas por toda a classe. Eles não operam em instâncias, mas apenas nas propriedades estáticas.
class Foo {
public static function bar() {}
}
Constantes - constantes resolvidas em classe. Não indo mais fundo aqui, mas adicionando a integridade:
class Foo {
const BAR = 1;
}
Então, basicamente, estamos armazenando informações no contêiner de classe e objeto usando "dicas" sobre estática que identificam se a informação é compartilhada (e, portanto, estática) ou não (e, portanto, dinâmica).
Dentro de um método, a instância de um objeto é representada pela $this
variável O estado atual desse objeto está lá e a mutação (alteração) de qualquer propriedade resultará em uma alteração nessa instância (mas não em outras).
Se um método é chamado estaticamente, a $this
variável não está definida . Isso ocorre porque não há instância associada a uma chamada estática.
O interessante aqui é como as chamadas estáticas são feitas. Então, vamos falar sobre como acessamos o estado:
Então agora que armazenamos esse estado, precisamos acessá-lo. Isso pode ser um pouco complicado (ou muito mais que um pouco), então vamos dividir isso em dois pontos de vista: de fora de uma instância / classe (digamos, de uma chamada de função normal ou do escopo global) e dentro de uma instância / class (de dentro de um método no objeto).
Do lado de fora de uma instância / classe, nossas regras são bastante simples e previsíveis. Temos dois operadores e cada um nos diz imediatamente se estamos lidando com uma instância ou uma classe estática:
->
- operador de objeto - sempre é usado quando estamos acessando uma instância.
$bob = new Person;
echo $bob->name;
É importante observar que a chamada Person->foo
não faz sentido (já que Person
é uma classe, não uma instância). Portanto, esse é um erro de análise.
::
- scope-resolution-operator - Isso sempre é usado para acessar uma propriedade ou método estático de classe.
echo Foo::bar()
Além disso, podemos chamar um método estático em um objeto da mesma maneira:
echo $foo::bar()
É extremamente importante observar que, quando fazemos isso de fora , a instância do objeto fica oculta do bar()
método. Significando que é exatamente o mesmo que em execução:
$class = get_class($foo);
$class::bar();
Portanto, $this
não está definido na chamada estática.
As coisas mudam um pouco aqui. Os mesmos operadores são usados, mas seu significado se torna significativamente desfocado.
O operador de objeto ->
ainda é usado para fazer chamadas para o estado da instância do objeto.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Chamar o bar()
método $foo
(uma instância de Foo
) usando o operador de objeto: $foo->bar()
resultará na versão da instância de $a
.
Então é assim que esperamos.
O significado do ::
operador muda. Depende do contexto da chamada para a função atual:
Dentro de um contexto estático
Dentro de um contexto estático, todas as chamadas feitas usando ::
também serão estáticas. Vejamos um exemplo:
class Foo {
public function bar() {
return Foo::baz();
}
public function baz() {
return isset($this);
}
}
A chamada Foo::bar()
chamará o baz()
método estaticamente e, portanto $this
, não será preenchida. Vale a pena notar que nas versões recentes do PHP (5.3+) isso acionará um E_STRICT
erro, porque estamos chamando métodos não estáticos estaticamente.
Dentro de um contexto de instância
Em um contexto de instância, por outro lado, as chamadas feitas usando ::
dependem do receptor da chamada (o método que estamos chamando). Se o método for definido como static
, ele usará uma chamada estática. Caso contrário, ele encaminhará as informações da instância.
Portanto, observando o código acima, a chamada $foo->bar()
retornará true
, pois a chamada "estática" acontece dentro de um contexto de instância.
Faz sentido? Não achava isso. É confuso.
Como amarrar tudo junto usando nomes de classe é bastante sujo, o PHP fornece três palavras-chave básicas de "atalho" para facilitar a resolução do escopo.
self
- Refere-se ao nome da classe atual. O self::baz()
mesmo acontece Foo::baz()
com a Foo
classe (qualquer método nela).
parent
- Refere-se ao pai da classe atual.
static
- Refere-se à classe chamada. Graças à herança, as classes filho podem substituir métodos e propriedades estáticas. Portanto, chamá-los usando o static
nome de uma classe em vez de um nome de classe nos permite resolver de onde a chamada veio, em vez do nível atual.
A maneira mais fácil de entender isso é começar a examinar alguns exemplos. Vamos escolher uma aula:
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();
}
}
Agora, também estamos olhando para herança aqui. Ignore por um momento que este é um modelo de objeto ruim, mas vamos ver o que acontece quando brincamos com isso:
$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
Portanto, o contador de ID é compartilhado entre as instâncias e os filhos (porque estamos usando self
para acessá-lo. Se o usássemos static
, poderíamos substituí-lo em uma classe filho).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Observe que estamos sempre executando o método da Person::getName()
instância . Mas estamos usando o parent::getName()
para fazer isso em um dos casos (o caso filho). É isso que torna essa abordagem poderosa.
Observe que o contexto de chamada é o que determina se uma instância é usada. Portanto:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Nem sempre é verdade.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Agora é realmente estranho aqui. Estamos chamando uma classe diferente, mas a $this
que é passada para o Foo::isFoo()
método é a instância de $bar
.
Isso pode causar todos os tipos de erros e problemas conceituais com o WTF. Então eu sugiro evitar o ::
operador de dentro métodos de instância em qualquer coisa, exceto esses três "atalho" palavras-chave virtuais ( static
, self
, e parent
).
Observe que métodos e propriedades estáticas são compartilhados por todos. Isso os torna basicamente variáveis globais. Com todos os mesmos problemas que vêm com globais. Portanto, eu hesitaria muito em armazenar informações em métodos / propriedades estáticas, a menos que você se sinta à vontade em ser verdadeiramente global.
Em geral, convém usar o que é conhecido como ligação estática tardia usando em static
vez de self
. Mas observe que eles não são a mesma coisa; portanto, dizer "sempre use em static
vez de self
é realmente míope. Em vez disso, pare e pense na chamada que deseja fazer e pense se deseja que as classes filho possam substituir a estática resolvida". ligar.
Que pena, volte e leia. Pode ser muito longo, mas é longo, porque esse é um tópico complexo
Ok, tudo bem. Em resumo, self
é usado para referenciar o nome da classe atual dentro de uma classe, onde, como $this
se refere à instância do objeto atual . Observe que self
é um atalho de copiar / colar. Você pode substituí-lo com segurança pelo nome da sua classe e funcionará bem. Mas $this
é uma variável dinâmica que não pode ser determinada com antecedência (e pode até não ser sua classe).
Se o operador de objeto for usado ( ->
), você sempre saberá que está lidando com uma instância. Se o operador de resolução de escopo for usado ( ::
), você precisará de mais informações sobre o contexto (já estamos em um contexto de objeto? Estamos fora de um objeto? Etc).
$this
não será definido se você seguir "Padrões Estritos" e não chamar métodos estaticamente que não sejam definidos como estáticos. Vejo o resultado que você explicou aqui: 3v4l.org/WeHVM Concordou, muito estranho.
Foo::isFoo()
é chamado estaticamente, $this
não será definido. Esse é um comportamento mais intuitivo na minha opinião. - Outro resultado diferente é dado se Bar
for estendido de Foo
. Então a chamada Foo::isFoo()
estaria realmente dentro do contexto da instância (não específico do PHP7).
self
(não $ self) refere-se ao tipo de classe, em que como $this
refere-se à instância atual da classe. self
é para uso em funções de membro estático para permitir o acesso a variáveis de membro estático. $this
é usado em funções-membro não estáticas e é uma referência à instância da classe na qual a função-membro foi chamada.
Porque this
é um objeto, você o usa como:$this->member
Como self
não é um objeto, é basicamente um tipo que se refere automaticamente à classe atual, você o usa como:self::member
$this->
é usado para se referir a uma instância específica de variáveis de uma classe (variáveis de membro) ou métodos.
Example:
$derek = new Person();
$ derek agora é uma instância específica de Person. Toda pessoa tem um nome e sobrenome, mas $ derek tem nome e sobrenome específicos (Derek Martin). Dentro da instância $ derek, podemos nos referir a esses como $ this-> first_name e $ this-> last_name
ClassName :: é usado para se referir a esse tipo de classe e suas variáveis estáticas, métodos estáticos. Se ajudar, você pode substituir mentalmente a palavra "estático" por "compartilhado". Por serem compartilhados, não podem se referir a $ this, que se refere a uma instância específica (não compartilhada). Variáveis estáticas (ou seja, estática $ db_connection) podem ser compartilhadas entre todas as instâncias de um tipo de objeto. Por exemplo, todos os objetos de banco de dados compartilham uma única conexão (conexão estática $).
Exemplo de variáveis estáticas: finja que temos uma classe de banco de dados com uma variável de membro único: static $ num_connections; Agora, coloque isso no construtor:
function __construct()
{
if(!isset $num_connections || $num_connections==null)
{
$num_connections=0;
}
else
{
$num_connections++;
}
}
Assim como os objetos têm construtores, eles também têm destruidores, que são executados quando o objeto morre ou é desativado:
function __destruct()
{
$num_connections--;
}
Toda vez que criamos uma nova instância, ela aumenta nosso contador de conexões em um. Sempre que destruirmos ou pararmos de usar uma instância, ele diminuirá o contador de conexões em um. Dessa maneira, podemos monitorar o número de instâncias do objeto de banco de dados que usamos:
echo DB::num_connections;
Como $ num_connections é estático (compartilhado), ele refletirá o número total de objetos de banco de dados ativos. Você pode ter visto essa técnica usada para compartilhar conexões de banco de dados entre todas as instâncias de uma classe de banco de dados. Isso é feito porque a criação da conexão com o banco de dados leva muito tempo, portanto, é melhor criar apenas uma e compartilhá-la (isso é chamado de Padrão Singleton).
Métodos estáticos (por exemplo, public static View :: format_phone_number ($ digits)) podem ser usados SEM primeiro instanciar um desses objetos (ou seja, eles não se referem internamente a $ this).
Exemplo 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 você pode ver, a função estática pública prettyName não sabe nada sobre o objeto. É apenas trabalhar com os parâmetros que você passa, como uma função normal que não faz parte de um objeto. Por que se preocupar, então, se pudéssemos tê-lo como parte do objeto?
SELF :: Se você estiver codificando fora do objeto que possui o método estático ao qual deseja se referir, deverá chamá-lo usando o nome do objeto View :: format_phone_number ($ phone_number); Se você está codificando dentro do objeto que possui o método estático que você deseja consultar, você pode tanto usar o nome View :: format_phone_number do objeto ($ pn), ou você pode usar o self :: format_phone_number ($ pn) atalho
O mesmo vale para variáveis estáticas: Exemplo: View :: templates_path versus self :: templates_path
Dentro da classe DB, se estivéssemos nos referindo a um método estático de outro objeto, usaríamos o nome do objeto: Exemplo: Session :: getUsersOnline ();
Mas se a classe DB quisesse se referir a sua própria variável estática, ela apenas diria self: Exemplo: self :: connection;
Espero que ajude a esclarecer as coisas :)
$
sinal. Por exemploself::$templates_path
A partir deste post :
self
refere-se à classe atualself
pode ser usado para chamar funções estáticas e referenciar variáveis de membro estáticasself
pode ser usado dentro de funções estáticasself
também pode desativar o comportamento polimórfico ignorando a tabela$this
refere-se ao objeto atual$this
pode ser usado para chamar funções estáticas$this
não deve ser usado para chamar variáveis de membro estáticas. Use emself
vez disso.$this
não pode ser usado dentro de funções estáticas
No PHP, você usa a palavra-chave self para acessar propriedades e métodos estáticos.
O problema é que você pode substituir $this->method()
por self::method()
qualquer lugar, independentemente de method()
ser declarado estático ou não. Então, qual deles você deve 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();
Neste exemplo, self::who()
sempre produzirá 'pai', enquanto $this->who()
dependerá de qual classe o objeto possui.
Agora podemos ver que self refere-se à classe na qual é chamado, enquanto $this
refere-se à classe do objeto atual .
Portanto, você deve usar o self somente quando $this
não estiver disponível ou quando não desejar permitir que as classes descendentes substituam o método atual.
Dentro de uma definição de classe, $this
refere-se ao objeto atual, enquanto self
refere-se à classe atual.
É necessário fazer referência a um elemento de classe usando self
e a um elemento de objeto usando $this
.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Aqui está um exemplo do uso correto de $ this e self para variáveis de membro não estáticas e 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();
?>
De acordo com http://www.php.net/manual/en/language.oop5.static.php, não existe $self
. Existe apenas $this
, para se referir à instância atual da classe (o objeto), e self, que pode ser usado para se referir a membros estáticos de uma classe. A diferença entre uma instância de objeto e uma classe entra em jogo aqui.
Creio que a questão não era se você pode chamar o membro estático da classe ligando ClassName::staticMember
. A questão era qual a diferença entre usar self::classmember
e $this->classmember
.
Por exemplo, os dois exemplos a seguir funcionam sem erros, independentemente de você usar self::
ou nã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;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
refere-se à classe atual (na qual é chamada),
$this
refere-se ao objeto atual. Você pode usar estática em vez de si mesma. Veja o exemplo:
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();
Saída: filho pai
$this
para refere-se ao objeto atual.static
refere-se ao objeto atual.self
refere-se à classe exata em que foi definida.parent
refere-se ao pai da classe exata em que foi definido.Veja o exemplo a seguir, que mostra 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"
Na maioria das vezes você deseja consultar a classe atual e é por isso que você usa static
ou $this
. No entanto, há momentos em que você precisa, self
porque deseja a classe original, independentemente do que a estender. (Muito, muito raramente)
Como ninguém aqui falou sobre performances, aqui está uma pequena referência que eu fiz (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
Esses são os resultados para 2 000 000 execuções, e aqui está o código que eu usei:
<?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();
1 / 2e9 s = 0.5 ns
nos dias de hoje
use
palavra - chave tbh, mas não tenho mais o PHP para refazer uma referência e não sinto vontade de reinstalá-la.
Encontrei a mesma pergunta e a resposta simples é:
$this
requer uma instância da classeself::
nãoSempre que você estiver usando métodos estáticos ou atributos estáticos e quiser chamá-los sem ter um objeto da classe instanciado, precisará usá self:
-los para chamá-los, porque $this
sempre exige que o objeto seja criado.
$this
refere-se ao objeto de classe atual, self
refere-se à classe atual (Não objeto). A classe é o blueprint do objeto. Então você define uma classe, mas constrói objetos.
Então, em outras palavras, use self for static
ethis for none-static members or methods
.
também no cenário filho / pai self / parent
é usado principalmente para identificar membros e métodos da classe pai e filho.
Além disso, uma vez que $this::
ainda não foi discutido.
Apenas para fins informativos, a partir do PHP 5.3, quando se lida com objetos instanciados para obter o valor atual do escopo, em vez de usar static::
, pode-se usar $this::
como alternativa .
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
O uso do código acima não é uma prática comum ou recomendada, mas apenas para ilustrar seu uso e é mais como um "Você sabia?" em referência à pergunta do pôster original.
Também representa o uso de, $object::CONSTANT
por exemplo, echo $foo::NAME;
em oposição a$this::NAME;
Caso 1: uso self
pode ser usado para constantes de classe
classe classA { const FIXED_NUMBER = 4; self :: POUNDS_TO_KILOGRAMS }
Se você quiser chamá-lo fora da classe, use classA::POUNDS_TO_KILOGRAMS
para acessar as constantes
Caso 2: Para propriedades estáticas
classe classC { função pública __construct () { self :: $ _ counter ++; $ this-> num = self :: $ _ counter; } }
De acordo com php.net há três palavras-chave especiais neste contexto: self
, parent
e static
. Eles são usados para acessar propriedades ou métodos de dentro da definição de classe.
$this
, por outro lado, é usado para chamar uma instância e métodos de qualquer classe, desde que essa classe esteja acessível.
self :: palavra-chave usada para a classe atual e basicamente é usada para acessar membros, métodos e constantes estáticos. Mas no caso de $ this, você não pode chamar o membro estático, método e funções.
Você pode usar a palavra-chave self :: em outra classe e acessar os membros, método e constantes estáticos. Quando será estendido da classe pai e o mesmo no caso de $ this keyword. Você pode acessar os membros não estáticos, método e função em outra classe quando ela for estendida da classe pai.
O código fornecido abaixo é um exemplo de self :: e $ this keyword. Basta copiar e colar o código no seu arquivo de código e ver a saída.
class cars{
var $doors=4;
static $car_wheel=4;
public function car_features(){
echo $this->doors." Doors <br>";
echo self::$car_wheel." Wheels <br>";
}
}
class spec extends cars{
function car_spec(){
print(self::$car_wheel." Doors <br>");
print($this->doors." Wheels <br>");
}
}
/********Parent class output*********/
$car = new cars;
print_r($car->car_features());
echo "------------------------<br>";
/********Extend class from another class output**********/
$car_spec_show=new spec;
print($car_spec_show->car_spec());