In PHP 5, qual è la differenza tra l'utilizzo di self
e $this
?
Quando è appropriato?
In PHP 5, qual è la differenza tra l'utilizzo di self
e $this
?
Quando è appropriato?
Risposte:
Utilizzare
$this
per fare riferimento all'oggetto corrente. Utilizzareself
per fare riferimento alla classe corrente. In altre parole, utilizzare$this->member
per membri non statici, utilizzareself::$member
per membri statici.
Ecco un esempio di utilizzo corretto di $this
e self
per variabili membro non statiche e statiche:
<?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();
?>
Ecco un esempio di utilizzo errato di $this
e self
per variabili membro non statiche e statiche:
<?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();
?>
Ecco un esempio di polimorfismo con $this
funzioni 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();
?>
Ecco un esempio di soppressione del comportamento polimorfico usando self
per le funzioni 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();
?>
L'idea è che
$this->foo()
chiama lafoo()
funzione membro di qualunque sia il tipo esatto dell'oggetto corrente. Se l'oggetto è ditype X
, quindi chiamaX::foo()
. Se l'oggetto è ditype Y
, chiamaY::foo()
. Ma con self :: foo (),X::foo()
viene sempre chiamato.
Da http://www.phpbuilder.com/board/showthread.php?t=10354489 :
self
viene utilizzato con l'operatore di risoluzione dell'ambito ::
per fare riferimento alla classe corrente; questo può essere fatto sia in contesti statici che non statici. Inoltre, è perfettamente legale utilizzare $this
per chiamare metodi statici (ma non per fare riferimento ai campi).
$this::
?
La parola chiave self NON si riferisce semplicemente alla "classe corrente", almeno non in un modo che ti limiti ai membri statici. Nel contesto di un membro non statico, self
fornisce anche un modo per bypassare la vtable ( vedere wiki su vtable ) per l'oggetto corrente. Proprio come puoi usare parent::methodName()
per chiamare la versione genitore di una funzione, così puoi chiamare self::methodName()
per chiamare l'implementazione delle classi corrente di un metodo.
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();
Questo produrrà:
Ciao, sono Ludwig il geek
Addio da Ludwig la persona
sayHello()
usa il $this
puntatore, quindi la vtable viene invocata per chiamare Geek::getTitle()
.
sayGoodbye()
usa self::getTitle()
, quindi la vtable non viene utilizzata e Person::getTitle()
viene chiamata. In entrambi i casi, abbiamo a che fare con il metodo di un oggetto istanziato e abbiamo accesso al $this
puntatore all'interno delle funzioni chiamate.
self
si trova" / "la definizione della classe, è una parte letterale di" sia "la classe dell'oggetto" (che in realtà sarebbe static
).
$this::
?
$this::
; tutti i possibili casi sono già coperti da sintassi più comunemente utilizzate. A seconda di quello che vuoi dire, l'uso $this->
, self::
o static::
.
NON USARE self::
, usarestatic::
C'è un altro aspetto di sé: che vale la pena menzionare. Si self::
riferisce fastidiosamente al campo di applicazione al punto di definizione, non al punto di esecuzione . Considera questa semplice classe con due metodi:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
Se chiamiamo Person::status()
vedremo "La persona è viva". Ora considera cosa succede quando creiamo una classe che eredita da questo:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Chiamando Deceased::status()
ci aspetteremmo di vedere "La persona è deceduta", tuttavia ciò che vediamo è "La persona è viva" poiché l'ambito contiene la definizione del metodo originale quando è self::getStatus()
stata definita la chiamata a .
PHP 5.3 ha una soluzione. l' static::
operatore di risoluzione implementa "associazione statica tardiva", che è un modo elegante per dire che è legato all'ambito della classe chiamata. Modificare la riga in status()
a static::getStatus()
ed i risultati sono ciò che ci si aspetterebbe. Nelle versioni precedenti di PHP dovrai trovare un kludge per farlo.
Vedi documentazione PHP
Quindi per rispondere alla domanda non come chiesto ...
$this->
si riferisce all'oggetto corrente (un'istanza di una classe), mentre si static::
riferisce a una classe
getStatus
metodo come uno che chiamerei un'istanza di classe, non una classe.
self::
, puoi ottenerlo, meno confusamente, usando il nome specifico della classe, ad es MyClass::
.
Per capire veramente di cosa stiamo parlando quando parliamo di self
contro $this
, dobbiamo davvero scavare in quello che sta succedendo a livello concettuale e pratico. Non credo che nessuna delle risposte lo faccia in modo appropriato, quindi ecco il mio tentativo.
Cominciamo parlando di cosa sono una classe e un oggetto .
Allora, che cosa è un codice categoria ? Molte persone lo definiscono come un progetto o un modello per un oggetto. In effetti, puoi leggere di più sulle classi in PHP qui . E fino a un certo punto è così. Diamo un'occhiata a una classe:
class Person {
public $name = 'my name';
public function sayHello() {
echo "Hello";
}
}
Come puoi vedere, esiste una proprietà su quella classe chiamata $name
e un metodo (funzione) chiamato sayHello()
.
È molto importante notare che la classe è una struttura statica. Ciò significa che la classe Person
, una volta definita, è sempre la stessa ovunque la guardi.
Un oggetto d'altra parte è ciò che viene chiamato un'istanza di una classe. Ciò significa che prendiamo il "progetto" della classe e lo usiamo per fare una copia dinamica. Questa copia ora è specificamente legata alla variabile in cui è archiviata. Pertanto, qualsiasi modifica a un'istanza è locale a tale istanza.
$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"
Creiamo nuove istanze di una classe utilizzando l' new
operatore.
Pertanto, diciamo che una classe è una struttura globale e un oggetto è una struttura locale. Non preoccuparti di quella ->
sintassi divertente , ci entreremo tra poco.
Un'altra cosa di cui dovremmo parlare è che possiamo verificare se un'istanza è una instanceof
classe particolare: $bob instanceof Person
che restituisce un valore booleano se l' $bob
istanza è stata creata usando la Person
classe, o un figlio di Person
.
Quindi scaviamo un po 'in ciò che effettivamente contiene una classe. Esistono 5 tipi di "cose" che una classe contiene:
Proprietà : pensa a queste come variabili che ogni istanza conterrà.
class Foo {
public $bar = 1;
}
Proprietà statiche - Pensa a queste come variabili condivise a livello di classe. Ciò significa che non vengono mai copiati da ciascuna istanza.
class Foo {
public static $bar = 1;
}
Metodi : sono funzioni che ogni istanza conterrà (e opererà su istanze).
class Foo {
public function bar() {}
}
Metodi statici : si tratta di funzioni condivise nell'intera classe. Essi non operano su istanze, ma invece sul solo le proprietà statiche.
class Foo {
public static function bar() {}
}
Costanti : costanti risolte in classe. Non andare più in profondità qui, ma aggiungendo per completezza:
class Foo {
const BAR = 1;
}
Quindi, in sostanza, stiamo memorizzando informazioni sulla classe e sul contenitore oggetti usando "suggerimenti" su static che identificano se le informazioni sono condivise (e quindi statiche) o meno (e quindi dinamiche).
All'interno di un metodo, l'istanza di un oggetto è rappresentata dalla $this
variabile. Lo stato corrente di quell'oggetto è presente e la mutazione (modifica) di qualsiasi proprietà comporterà una modifica a quell'istanza (ma non ad altre).
Se un metodo viene chiamato staticamente, la $this
variabile non è definita . Questo perché non esiste un'istanza associata a una chiamata statica.
La cosa interessante qui è come vengono fatte le chiamate statiche. Quindi parliamo di come accediamo allo stato:
Quindi ora che abbiamo memorizzato quello stato, dobbiamo accedervi. Questo può diventare un po 'complicato (o molto più di un po'), quindi dividiamolo in due punti di vista: dall'esterno di un'istanza / classe (diciamo da una normale chiamata di funzione o dall'ambito globale) e all'interno di un'istanza / class (dall'interno di un metodo sull'oggetto).
Dall'esterno di un'istanza / classe, le nostre regole sono abbastanza semplici e prevedibili. Abbiamo due operatori e ognuno ci dice immediatamente se abbiamo a che fare con un'istanza o una classe statica:
->
- object-operator : viene sempre utilizzato quando si accede a un'istanza.
$bob = new Person;
echo $bob->name;
È importante notare che la chiamata Person->foo
non ha senso (poiché Person
è una classe, non un'istanza). Pertanto, questo è un errore di analisi.
::
- scope-risoluzione-operatore : viene sempre utilizzato per accedere a una proprietà o un metodo statici di classe.
echo Foo::bar()
Inoltre, possiamo chiamare un metodo statico su un oggetto allo stesso modo:
echo $foo::bar()
È estremamente importante notare che quando lo facciamo dall'esterno , l'istanza dell'oggetto è nascosta dal bar()
metodo. Ciò significa che è esattamente lo stesso della corsa:
$class = get_class($foo);
$class::bar();
Pertanto, $this
non è definito nella chiamata statica.
Le cose cambiano un po 'qui. Vengono utilizzati gli stessi operatori, ma il loro significato diventa significativamente sfocato.
L' operatore oggetto ->
viene ancora utilizzato per effettuare chiamate allo stato dell'istanza dell'oggetto.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Richiamare il bar()
metodo su $foo
(un'istanza di Foo
) utilizzando l'operatore oggetto: $foo->bar()
comporterà la versione dell'istanza di$a
.
Quindi è così che ci aspettiamo.
Il significato ::
dell'operatore però cambia. Dipende dal contesto della chiamata alla funzione corrente:
In un contesto statico
In un contesto statico, anche tutte le chiamate effettuate utilizzando ::
saranno statiche. Diamo un'occhiata a un esempio:
class Foo {
public function bar() {
return Foo::baz();
}
public function baz() {
return isset($this);
}
}
Chiamando Foo::bar()
chiamerà il baz()
metodo statico, e quindi $this
sarà non essere popolato. Vale la pena notare che nelle ultime versioni di PHP (5.3+) questo causerà un E_STRICT
errore, perché stiamo chiamando staticamente metodi non statici.
In un contesto di istanza
D'altro canto, all'interno di un contesto di istanza, le chiamate effettuate tramite ::
dipendono dal destinatario della chiamata (il metodo che stiamo chiamando). Se il metodo è definito comestatic
, utilizzerà una chiamata statica. In caso contrario, inoltrerà le informazioni sull'istanza.
Quindi, guardando il codice sopra, la chiamata $foo->bar()
tornerà true
, poiché la chiamata "statica" avviene all'interno di un contesto di istanza.
Ha senso? Non la pensavo così. È confusionario.
Poiché legare tutto insieme usando i nomi delle classi è piuttosto sporco, PHP fornisce 3 parole chiave di base "scorciatoia" per facilitare la risoluzione dell'ambito.
self
- Questo si riferisce al nome della classe corrente. Quindi self::baz()
è lo stesso Foo::baz()
della Foo
classe (qualsiasi metodo su di essa).
parent
- Questo si riferisce al genitore della classe corrente.
static
- Questo si riferisce alla classe chiamata. Grazie all'ereditarietà, le classi figlio possono sovrascrivere metodi e proprietà statiche. Quindi chiamarli usando static
invece di un nome di classe ci consente di risolvere da dove proviene la chiamata, piuttosto che il livello corrente.
Il modo più semplice per capirlo è iniziare a guardare alcuni esempi. Scegliamo un corso:
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();
}
}
Ora, stiamo anche guardando l'eredità qui. Ignora per un momento che questo è un cattivo modello a oggetti, ma diamo un'occhiata a cosa succede quando giochiamo con questo:
$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
Quindi il contatore ID è condiviso da entrambe le istanze e dai figli (perché stiamo usando self
per accedervi. Se lo usassimo static
, potremmo sovrascriverlo in una classe figlio).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Nota che stiamo eseguendo il metodo di Person::getName()
istanza ogni volta. Ma stiamo usando ilparent::getName()
per farlo in uno dei casi (il caso figlio). Questo è ciò che rende potente questo approccio.
Si noti che il contesto chiamante è ciò che determina se viene utilizzata un'istanza. Perciò:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Non è sempre vero.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Ora è davvero strano qui. Stiamo chiamando una classe diversa, ma quella $this
che viene passata al Foo::isFoo()
metodo è l'istanza di$bar
.
Ciò può causare tutti i tipi di bug e concetti WTF concettuali. Così mi piacerebbe consiglio vivamente di evitare l' ::
operatore all'interno di metodi di istanza su nulla, tranne quelle tre virtuali "scorciatoia" parole chiave ( static
, self
, eparent
).
Si noti che i metodi e le proprietà statici sono condivisi da tutti. Ciò li rende sostanzialmente variabili globali. Con tutti gli stessi problemi che derivano dai globali. Quindi esiterei davvero a conservare le informazioni in metodi / proprietà statici a meno che non ti senta a tuo agio nel fatto che siano veramente globali.
In generale, ti consigliamo di utilizzare il cosiddetto Late-Static-Binding utilizzando static
anziché self
. Ma nota che non sono la stessa cosa, quindi dire "usa sempre static
invece di self
è davvero miope. Invece, fermati e pensa alla chiamata che vuoi fare e pensa se vuoi che le classi secondarie siano in grado di scavalcare quella statica risolta chiamata.
Peccato, torna indietro e leggilo. Potrebbe essere troppo lungo, ma è così lungo perché questo è un argomento complesso
Ok bene. In breve, self
viene utilizzato per fare riferimento al nome della classe corrente all'interno di una classe, dove come si $this
riferisce all'istanza dell'oggetto corrente . Si noti che self
è una scorciatoia copia / incolla. Puoi tranquillamente sostituirlo con il nome della tua classe e funzionerà benissimo. Ma$this
è una variabile dinamica che non può essere determinata in anticipo (e potrebbe anche non essere la tua classe).
Se viene utilizzato l'operatore oggetto ( ->
), allora sai sempre che hai a che fare con un'istanza. Se viene utilizzato l'operatore di risoluzione dell'ambito ( ::
), sono necessarie ulteriori informazioni sul contesto (siamo già in un contesto di oggetto? Siamo al di fuori di un oggetto? Ecc.).
$this
non sarà definito se segui "Standard rigorosi" e non chiami metodi staticamente che non sono definiti statici. Vedo il risultato che hai spiegato qui: 3v4l.org/WeHVM D'accordo, davvero strano.
Foo::isFoo()
viene chiamato staticamente, $this
non verrà definito. Questo è un comportamento più intuitivo secondo me. - Un altro risultato diverso è dato se Bar
si dovesse estendere Foo
. Quindi la chiamata Foo::isFoo()
verrebbe effettivamente inserita nel contesto dell'istanza (non specifico di PHP7).
self
(non $ self) si riferisce al tipo di classe, dove come si $this
riferisce all'istanza corrente della classe. self
è da utilizzare nelle funzioni membro statico per consentire l'accesso alle variabili membro statico. $this
viene utilizzato nelle funzioni membro non statiche ed è un riferimento all'istanza della classe su cui è stata chiamata la funzione membro.
Perché this
è un oggetto, lo usi come:$this->member
Poiché self
non è un oggetto, è fondamentalmente un tipo che si riferisce automaticamente alla classe corrente, lo usi come:self::member
$this->
viene utilizzato per fare riferimento a un'istanza specifica delle variabili o dei metodi di una classe.
Example:
$derek = new Person();
$ derek è ora un'istanza specifica di Person. Ogni persona ha un nome e un cognome, ma $ derek ha un nome e un cognome specifici (Derek Martin). All'interno dell'istanza $ derek, possiamo fare riferimento a quelli come $ this-> first_name e $ this-> last_name
ClassName :: è usato per fare riferimento a quel tipo di classe e alle sue variabili statiche, ai metodi statici. Se aiuta, puoi sostituire mentalmente la parola "statico" con "condiviso". Poiché sono condivisi, non possono fare riferimento a $ this, che fa riferimento a un'istanza specifica (non condivisa). Le variabili statiche (ovvero $ db_connection statico) possono essere condivise tra tutte le istanze di un tipo di oggetto. Ad esempio, tutti gli oggetti del database condividono una singola connessione (connessione $ statica).
Esempio di variabili statiche: fingiamo di avere una classe di database con una variabile a membro singolo: static $ num_connections; Ora, mettilo nel costruttore:
function __construct()
{
if(!isset $num_connections || $num_connections==null)
{
$num_connections=0;
}
else
{
$num_connections++;
}
}
Proprio come gli oggetti hanno costruttori, hanno anche i distruttori, che vengono eseguiti quando l'oggetto muore o non è impostato:
function __destruct()
{
$num_connections--;
}
Ogni volta che creiamo una nuova istanza, aumenterà il nostro contatore di connessioni di una. Ogni volta che distruggiamo o smettiamo di usare un'istanza, il contatore delle connessioni diminuirà di uno. In questo modo, possiamo monitorare il numero di istanze dell'oggetto database che abbiamo in uso con:
echo DB::num_connections;
Poiché $ num_connections è statico (condiviso), rifletterà il numero totale di oggetti di database attivi. Potresti aver visto questa tecnica utilizzata per condividere le connessioni al database tra tutte le istanze di una classe di database. Questo perché la creazione della connessione al database richiede molto tempo, quindi è meglio crearne una sola e condividerla (questo si chiama Singleton Pattern).
I metodi statici (ad es. View statico pubblico :: format_phone_number ($ cifre)) possono essere utilizzati SENZA la prima istanza di uno di questi oggetti (ovvero non si riferiscono internamente a $ this).
Esempio di metodo statico:
public static function prettyName($first_name, $last_name)
{
echo ucfirst($first_name).' '.ucfirst($last_name);
}
echo Person::prettyName($derek->first_name, $derek->last_name);
Come puoi vedere, la funzione statica pubblica prettyName non sa nulla sull'oggetto. Funziona solo con i parametri che passi, come una normale funzione che non fa parte di un oggetto. Perché preoccuparsi, quindi, se potessimo semplicemente non averlo come parte dell'oggetto?
SELF :: Se stai codificando all'esterno dell'oggetto che ha il metodo statico a cui vuoi fare riferimento, devi chiamarlo usando il nome dell'oggetto View :: format_phone_number ($ phone_number); Se si esegue la codifica all'interno l'oggetto che ha il metodo statico si desidera fare riferimento, è possibile sia utilizzare il nome Vista :: format_phone_number dell'oggetto ($ pn), oppure è possibile utilizzare il self :: format_phone_number ($ pn) scorciatoia
Lo stesso vale per le variabili statiche: Esempio: View :: templates_path contro self :: templates_path
All'interno della classe DB, se ci riferissimo a un metodo statico di qualche altro oggetto, utilizzeremmo il nome dell'oggetto: Esempio: Session :: getUsersOnline ();
Ma se la classe DB volesse fare riferimento alla propria variabile statica, direbbe solo self: Esempio: self :: connection;
Spero che aiuti a chiarire le cose :)
$
segno. Ad esempioself::$templates_path
Da questo post del blog :
self
si riferisce alla classe correnteself
può essere utilizzato per chiamare funzioni statiche e fare riferimento a variabili membro staticheself
può essere utilizzato all'interno di funzioni staticheself
può anche disattivare il comportamento polimorfico bypassando la vtable$this
si riferisce all'oggetto corrente$this
può essere usato per chiamare funzioni statiche$this
non deve essere utilizzato per chiamare variabili membro statiche. Usaself
invece.$this
non può essere utilizzato all'interno di funzioni statiche
In PHP, usi la parola chiave self per accedere a proprietà e metodi statici.
Il problema è che è possibile sostituire $this->method()
con self::method()
qualsiasi luogo, a prescindere se method()
è dichiarato statico o no. Quindi quale dovresti usare?
Considera questo codice:
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();
In questo esempio, self::who()
verrà sempre generato 'parent', mentre $this->who()
dipenderà dalla classe che ha l'oggetto.
Ora possiamo vedere che self si riferisce alla classe in cui viene chiamato, mentre si $this
riferisce alla classe dell'oggetto corrente .
Quindi, dovresti usare sé solo quando $this
non è disponibile o quando non vuoi consentire alle classi discendenti di sovrascrivere il metodo corrente.
All'interno di una definizione di classe, si $this
riferisce all'oggetto corrente, mentreself
riferisce alla classe corrente.
È necessario fare riferimento a un elemento di classe utilizzando self
e fare riferimento a un elemento oggetto utilizzando $this
.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Ecco un esempio dell'uso corretto di $ this e self per le variabili membro non statiche e statiche:
<?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();
?>
Secondo http://www.php.net/manual/en/language.oop5.static.php non esiste $self
. C'è solo $this
, per fare riferimento all'istanza corrente della classe (l'oggetto), e self, che può essere usato per riferirsi a membri statici di una classe. La differenza tra un'istanza di oggetto e una classe entra in gioco qui.
Credo che la domanda non fosse se si può chiamare il membro statico della classe chiamando ClassName::staticMember
. La domanda era qual è la differenza tra l'utilizzo di self::classmember
e $this->classmember
.
Ad esempio, entrambi i seguenti esempi funzionano senza errori, sia che si usi 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;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
self
fa riferimento alla classe corrente (in cui viene chiamata),
$this
fa riferimento all'oggetto corrente. Puoi usare statico invece di sé. Vedi l'esempio:
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();
Uscita: figlio principale
$this
a si riferisce all'oggetto corrente.static
riferisce all'oggetto corrente.self
riferisce alla classe esatta in cui è stata definita.parent
riferisce al genitore della classe esatta in cui è stato definito.Vedere l'esempio seguente che mostra il sovraccarico.
<?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"
Il più delle volte si desidera fare riferimento alla classe corrente, motivo per cui si utilizza static
o $this
. Tuttavia, ci sono momenti in cui è necessario self
perché si desidera la classe originale indipendentemente da ciò che la estende. (Molto, Molto di rado)
Dato che qui nessuno parlava di performance, ecco un piccolo benchmark che ho fatto (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
Questi sono i risultati per 2 000 000 di esecuzioni ed ecco il codice che ho usato:
<?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
questi giorni
use
parola chiave tbh, ma non ho più PHP per rifare un benchmark e non ho davvero voglia di reinstallarlo.
Quando self
viene utilizzato con l' ::
operatore, si riferisce alla classe corrente, che può essere eseguita sia in contesti statici che non statici. $this
si riferisce all'oggetto stesso. Inoltre, è perfettamente legale utilizzare $this
per chiamare metodi statici (ma non fare riferimento ai campi).
Ho incontrato la stessa domanda e la risposta semplice è:
$this
richiede un'istanza della classeself::
non lo faOgni volta che si utilizzano metodi statici o attributi statici e si desidera chiamarli senza avere un'istanza di un oggetto della classe, è necessario utilizzarli self:
per chiamarli, poiché è $this
sempre necessario creare l'oggetto.
$this
si riferisce all'oggetto classe corrente, si self
riferisce alla classe corrente (non oggetto). La classe è il progetto dell'oggetto. Quindi definisci una classe, ma costruisci oggetti.
Quindi, in altre parole, utilizzare self for static
ethis for none-static members or methods
.
anche nello scenario figlio / genitore self / parent
viene utilizzato principalmente per identificare membri e metodi della classe figlio e genitore.
Inoltre da allora $this::
non è stato ancora discusso.
Solo a scopo informativo, a partire da PHP 5.3 quando si ha a che fare con oggetti istanziati per ottenere il valore di ambito corrente, al contrario dell'uso static::
, si può alternativamente usare $this::
così.
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
L'uso del codice sopra non è una pratica comune o raccomandata, ma serve semplicemente a illustrarne l'uso e ad agire come qualcosa di più di "Lo sapevi?" in riferimento alla domanda del poster originale.
Rappresenta anche l'uso di $object::CONSTANT
per esempio echo $foo::NAME;
rispetto a$this::NAME;
Utilizzare self
se si desidera chiamare un metodo di una classe senza creare un oggetto / istanza di quella classe, risparmiando così la RAM (a volte usare self per quello scopo). In altre parole, in realtà sta chiamando staticamente un metodo. Utilizzare this
per la prospettiva dell'oggetto.
Caso 1: utilizzare self
può essere utilizzato per le costanti di classe
class classA { const FIXED_NUMBER = 4; self :: POUNDS_TO_KILOGRAMS }
Se si desidera chiamarlo al di fuori della classe, utilizzare classA::POUNDS_TO_KILOGRAMS
per accedere alle costanti
Caso 2: per proprietà statiche
class classC { funzione pubblica __construct () { self :: $ _ contatore ++; $ this-> num = self :: $ _ counter; } }
Secondo php.net ci sono tre parole chiave speciali in questo contesto: self
, parent
e static
. Sono utilizzati per accedere a proprietà o metodi dall'interno della definizione della classe.
$this
d'altra parte, viene utilizzato per chiamare un'istanza e metodi di qualsiasi classe purché tale classe sia accessibile.
self :: parola chiave utilizzata per la classe corrente e sostanzialmente viene utilizzata per accedere a membri, metodi e costanti statici. Ma nel caso di $ this non è possibile chiamare il membro, il metodo e le funzioni statici.
È possibile utilizzare la parola chiave self :: in un'altra classe e accedere ai membri, al metodo e alle costanti statici. Quando sarà esteso dalla classe genitore e lo stesso nel caso di $ questa parola chiave. È possibile accedere ai membri, al metodo e alla funzione non statici in un'altra classe quando verrà estesa dalla classe padre.
Il codice fornito di seguito è un esempio di self :: e $ questa parola chiave. Basta copiare e incollare il codice nel file di codice e vedere l'output.
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());