Dans PHP 5, quelle est la différence entre self
et $this
?
Quand est-ce approprié?
Utilisez
$this
pour faire référence à l'objet actuel. Utilisezself
pour faire référence à la classe actuelle. En d'autres termes, utilisez$this->member
pour les membres non statiques, utilisezself::$member
pour les membres statiques.
Voici un exemple d'utilisation correcte de - de $this
et de self
pour des variables de membre non statiques et statiques:
<?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();
?>
Voici un exemple d'utilisation incorrecte de $this
et self
pour des variables de membre non statiques et statiques:
<?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();
?>
Voici un exemple de polymorphisme avec $this
pour les fonctions membres:
<?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();
?>
Voici un exemple de suppression du comportement polymorphe en utilisant self
pour les fonctions membres:
<?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'idée est que
$this->foo()
appelle la fonction membrefoo()
de quel que soit le type exact de l'objet actuel. Si l'objet est detype X
, il appelle doncX::foo()
. Si l'objet est detype Y
, il appelleY::foo()
. Mais avec self :: foo (),X::foo()
est toujours appelé.
De http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Par http://board.phpbuilder.com/member.php?145249-laserlight
Le mot-clé self NOT fait simplement référence à la "classe actuelle", du moins pas d'une manière qui vous limite aux membres statiques. Dans le contexte d'un membre non statique, self
fournit également un moyen de contourner la vtable ( voir le wiki sur vtable ) pour l'objet actuel. De même que vous pouvez utiliser parent::methodName()
pour appeler la version parents d'une fonction, vous pouvez également appeler self::methodName()
pour appeler l'implémentation en cours d'une méthode.
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();
Cela produira:
Bonjour, je suis Ludwig le geek
Au revoir de Ludwig la personne
sayHello()
utilise le pointeur $this
. La vtable est donc appelée pour appeler Geek::getTitle()
. sayGoodbye()
utilise self::getTitle()
, la vtable n'est donc pas utilisée et Person::getTitle()
est appelée. Dans les deux cas, nous traitons de la méthode d'un objet instancié et avons accès au pointeur $this
dans les fonctions appelées.
N'UTILISEZ PAS _self::
_, utilisez _static::
_
Il y a un autre aspect de soi :: qui mérite d'être mentionné. Ce qui est contrariant _self::
_ fait référence à la portée au moment de la définition et non au moment de l’exécution . Considérez cette classe simple avec deux méthodes:
_class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
_
Si nous appelons Person::status()
nous verrons "La personne est en vie". Maintenant, considérons ce qui se passe lorsque nous faisons une classe qui hérite de ceci:
_class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
_
En appelant Deceased::status()
, nous nous attendrions à voir "La personne est décédée". Cependant, nous voyons que "La personne est en vie", car la portée contient la définition de méthode originale lorsque l'appel à self::getStatus()
a été défini.
PHP 5.3 a une solution. l'opérateur de résolution static::
implémente la "liaison statique tardive", ce qui est une manière élégante de dire qu'elle est liée à la portée de la classe appelée. Modifiez la ligne dans status()
en static::getStatus()
et vous obtiendrez les résultats escomptés. Dans les anciennes versions de PHP, vous devrez trouver un kludge pour le faire.
Voir Documentation PHP
Donc, pour répondre à la question pas comme demandé ...
_$this->
_ fait référence à l'objet actuel (une instance d'une classe), alors que _static::
_ fait référence à une classe
Pour bien comprendre ce dont nous parlons lorsque nous parlons de self
par rapport à $this
, nous devons creuser ce qui se passe au niveau conceptuel et pratique. Je ne pense pas que les réponses donnent une réponse appropriée, voici donc ma tentative.
Commençons par parler de ce que sont un objet et un objet .
Alors, quel est a classe ? Beaucoup de gens le définissent comme un modèle ou un modèle pour un objet. En fait, vous pouvez en lire plus À propos des classes dans PHP Ici . Et dans une certaine mesure, c'est ce que c'est vraiment. Regardons une classe:
class Person {
public $name = 'my name';
public function sayHello() {
echo "Hello";
}
}
Comme vous pouvez le constater, il existe une propriété sur cette classe appelée $name
et une méthode (fonction) appelée sayHello()
.
Il est important très de noter que la classe est une structure statique. Ce qui signifie que la classe Person
, une fois définie, est toujours la même où que vous regardiez.
En revanche, un objet est ce qu'on appelle une instance d'une classe. Ce que cela signifie, c'est que nous prenons le "plan" de la classe et l'utilisons pour créer une copie dynamique. Cette copie est maintenant spécifiquement liée à la variable dans laquelle elle est stockée. Par conséquent, toute modification apportée à une instance est locale pour cette instance.
$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"
Nous créons de nouvelles instances d'une classe à l'aide de l'opérateur new
.
Par conséquent, nous disons qu'une classe est une structure globale et qu'un objet est une structure locale. Ne vous inquiétez pas de cette drôle de syntaxe ->
, nous allons l'expliquer dans un instant.
Une autre chose dont nous devrions parler, c'est que nous pouvons vérifier si une instance est un instanceof
une classe particulière: $bob instanceof Person
qui retourne un booléen si le L'instance $bob
a été créée à l'aide de la classe Person
, ou d'un enfant de Person
.
Alors, creusons un peu ce que contient une classe. Il y a 5 types de "choses" qu'une classe contient:
Propriétés - Considérez-les comme des variables que chaque instance contiendra.
class Foo {
public $bar = 1;
}
Propriétés statiques - Considérez-les comme des variables partagées au niveau de la classe. Cela signifie qu'ils ne sont jamais copiés par chaque instance.
class Foo {
public static $bar = 1;
}
Méthodes - Il s'agit de fonctions que chaque instance contiendra (et agira sur des instances).
class Foo {
public function bar() {}
}
Méthodes statiques - Il s'agit de fonctions partagées par toute la classe. Ils font not == opèrent sur les instances, mais uniquement sur les propriétés statiques.
class Foo {
public static function bar() {}
}
Constantes - Constantes résolues par classe. Ne pas aller plus loin ici, mais en ajoutant pour être complet:
class Foo {
const BAR = 1;
}
Donc, fondamentalement, nous stockons des informations sur la classe et le conteneur d’objets en utilisant des "astuces" sur static , qui identifient si les informations sont partagées (et donc statiques) ou non (et donc dynamiques). ).
À l'intérieur d'une méthode, l'instance d'un objet est représentée par la variable $this
. L'état actuel de cet objet est là, et la modification (modification) de toute propriété entraînera une modification de cette instance (mais pas des autres).
Si une méthode est appelée de manière statique, la variable $this
n'est pas définie . En effet, aucune instance n'est associée à un appel statique.
La chose intéressante ici est la façon dont les appels statiques sont effectués. Alors parlons de la façon dont nous accédons à l'état:
Alors maintenant que nous avons stocké cet état, nous devons y accéder. Cela peut devenir un peu délicat (ou manière plus que peu), divisons donc cela en deux points de vue: de l'extérieur d'une instance/classe (par exemple à partir d'un appel de fonction normal, ou de la portée globale), et à l'intérieur d'une instance/classe (à partir d'une méthode sur l'objet).
En dehors d'une instance/classe, nos règles sont assez simples et prévisibles. Nous avons deux opérateurs, et chacun nous dit immédiatement s'il s'agit d'une instance ou d'une classe statique:
->
- opérateur-objet - Ceci est toujours utilisé lorsque nous avons accès à une instance.
$bob = new Person;
echo $bob->name;
Il est important de noter que l'appel de Person->foo
n'a pas de sens (puisque Person
est une classe, pas une instance). C'est donc une erreur d'analyse.
::
- scope-resolution-operator - Ceci est toujours utilisé pour accéder à une propriété ou à une méthode de classe statique.
echo Foo::bar()
De plus, nous pouvons appeler une méthode statique sur un objet de la même manière:
echo $foo::bar()
Il est important de noter que lorsque nous faisons cela de l'extérieur , l'instance de l'objet est masquée par la méthode bar()
. Cela signifie que c'est exactement la même chose que de courir:
$class = get_class($foo);
$class::bar();
Par conséquent, $this
n'est pas défini dans l'appel statique.
Les choses changent un peu ici. Les mêmes opérateurs sont utilisés, mais leur signification devient considérablement floue.
L'opérateur d'objet ->
est toujours utilisé pour effectuer des appels vers l'état d'instance de l'objet.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
L'appel de la méthode bar()
sur $foo
(une instance de Foo
) à l'aide de l'opérateur d'objet: $foo->bar()
entraînera la version de l'instance de $a
.
C'est ce que nous attendons.
La signification de l'opérateur ::
bien que modifiée. Cela dépend du contexte de l'appel à la fonction en cours:
Dans un contexte statique
Dans un contexte statique, tous les appels effectués à l'aide de ::
seront également statiques. Regardons un exemple:
class Foo {
public function bar() {
return Foo::baz();
}
public function baz() {
return isset($this);
}
}
L'appel de Foo::bar()
appellera la méthode baz()
de manière statique, et donc $this
sera not être rempli. Il convient de noter que, dans les versions récentes de PHP (5.3+), ceci provoquera une erreur E_STRICT
, car nous appelons des méthodes non statiques de manière statique.
Dans un contexte d'instance
D'autre part, dans un contexte d'instance, les appels effectués à l'aide de ::
dépendent du destinataire de l'appel (la méthode que nous appelons). Si la méthode est définie comme static
, elle utilisera un appel statique. Si ce n'est pas le cas, il transmettra les informations sur l'instance.
Donc, en regardant le code ci-dessus, appeler $foo->bar()
retournera true
, puisque l'appel "statique" se produit à l'intérieur d'un contexte d'instance.
Avoir un sens? Je ne le pensais pas. C'est confu.
Parce que tout lier en utilisant des noms de classe est plutôt sale, PHP fournit 3 mots-clés de "raccourci" de base pour faciliter la résolution de périmètre.
self
- Ceci fait référence au nom de la classe actuelle. Donc, self::baz()
est identique à Foo::baz()
dans la classe Foo
(n'importe quelle méthode).
parent
- Ceci fait référence au parent de la classe en cours.
static
- Ceci fait référence à la classe appelée. Grâce à l'héritage, les classes enfants peuvent remplacer des méthodes et des propriétés statiques. Donc, les appeler en utilisant static
au lieu d’un nom de classe nous permet de déterminer l’origine de l’appel plutôt que le niveau actuel.
La meilleure façon de comprendre cela est de commencer à regarder quelques exemples. Choisissons un cours:
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();
}
}
Maintenant, nous examinons également l'héritage ici. Ignorer un instant qu'il s'agit d'un mauvais modèle d'objet, mais regardons ce qui se passe lorsque nous jouons avec ceci:
$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
Ainsi, le compteur d'ID est partagé entre les deux instances et les enfants (car nous utilisons self
pour y accéder. Si nous utilisions static
, nous pourrions le remplacer dans une classe enfant).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Notez que nous exécutons la méthode Person::getName()
à chaque fois. Mais nous utilisons la parent::getName()
pour le faire dans l’un des cas (le cas enfant). C'est ce qui rend cette approche puissante.
Notez que le contexte d'appel est ce qui détermine si une instance est utilisée. Donc:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
N'est-ce pas toujours vrai.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Maintenant, c'est vraiment bizarre ici. Nous appelons une classe différente, mais le $this
qui est transmis à la méthode Foo::isFoo()
est l'instance de $bar
.
Cela peut causer toutes sortes de bugs et conceptuels WTF-ery. Je suggérerais donc fortement d'éviter l'opérateur ::
dans les méthodes d'instance, sauf pour ces trois mots clés "raccourcis" virtuels (static
, self
et parent
). .
Notez que les méthodes et propriétés statiques sont partagées par tout le monde. Cela les rend fondamentalement des variables globales. Avec tous les mêmes problèmes qui viennent avec globals. Donc, j'hésiterais vraiment à stocker des informations dans des méthodes/propriétés statiques, à moins que vous ne soyez à l'aise avec le fait que ce soit vraiment global.
En général, vous voudrez utiliser ce que l'on appelle Late-Statique-Binding en utilisant static
au lieu de self
. Notez cependant qu’il ne s’agit pas de la même chose, alors dire "utilisez toujours static
au lieu de self
est vraiment à courte vue. Au lieu de cela, réfléchissez à l’appel que vous voulez faire et pensez si vous le souhaitez. les classes enfant doivent pouvoir remplacer cet appel résolu par statique .
Dommage, retournez le lire. C'est peut-être trop long, mais c'est tellement long parce que c'est un sujet complexe
OK bien. En bref, self
est utilisé pour référencer le nom de la classe actuelle dans une classe, où $this
fait référence à l'objet actuel exemple. Notez que self
est un raccourci copier/coller. Vous pouvez le remplacer en toute sécurité par le nom de votre classe et tout ira bien. Mais $this
est une variable dynamique qui ne peut pas être déterminée à l'avance (et peut-être même pas votre classe).
Si l'opérateur d'objet est utilisé (->
), vous savez toujours que vous avez affaire à une instance. Si l'opérateur de résolution est utilisé (::
), vous avez besoin d'informations supplémentaires sur le contexte (sommes-nous déjà dans un contexte d'objet? Sommes-nous en dehors d'un objet? Etc.).
self
(pas $ self) fait référence au type de la classe, où comme $this
se réfère au courant instance de la classe. self
est utilisé dans les fonctions de membre statique pour vous permettre d'accéder aux variables de membre statique. $this
est utilisé dans les fonctions membres non statiques et constitue une référence à l'instance de la classe sur laquelle la fonction membre a été appelée.
Comme this
est un objet, vous l'utilisez comme: $this->member
Comme self
n’est pas un objet, c’est essentiellement un type qui fait automatiquement référence à la classe actuelle, vous l’utilisez comme suit: self::member
$this->
est utilisé pour faire référence à une instance spécifique de variables d'une classe (variables membres) ou de méthodes.
Example:
$derek = new Person();
$ derek est maintenant une instance spécifique de Person. Chaque personne a un prénom et un nom, mais $ derek a un prénom et un nom spécifiques (Derek Martin). Dans l'instance $ derek, nous pouvons nous référer à ceux-ci comme $ this-> prénom_nom et $ this-> dernier_nom
ClassName :: est utilisé pour faire référence à ce type de classe et à ses variables statiques, méthodes statiques. Si cela vous aide, vous pouvez remplacer mentalement le mot "statique" par "partagé". Parce qu'ils sont partagés, ils ne peuvent pas faire référence à $ this, qui fait référence à une instance spécifique (non partagée). Les variables statiques (c'est-à-dire que statique $ db_connection) peuvent être partagées entre toutes les instances d'un type d'objet. Par exemple, tous les objets de base de données partagent une seule connexion (static $ connection).
Exemple de variables statiques: Prétendons que nous avons une classe de base de données avec une seule variable membre: static $ num_connections; Maintenant, mettez ceci dans le constructeur:
function __construct()
{
if(!isset $num_connections || $num_connections==null)
{
$num_connections=0;
}
else
{
$num_connections++;
}
}
Tout comme les objets ont des constructeurs, ils ont aussi des destructeurs, qui sont exécutés lorsque l'objet meurt ou n'est pas défini:
function __destruct()
{
$num_connections--;
}
Chaque fois que nous créons une nouvelle instance, notre compteur de connexions augmente d’un compteur. Chaque fois que nous détruisons ou cessons d'utiliser une instance, le compteur de connexion diminue d'un compteur. De cette manière, nous pouvons surveiller le nombre d'instances de l'objet de base de données utilisé:
echo DB::num_connections;
Comme $ num_connections est statique (partagé), il reflétera le nombre total d'objets de base de données actifs. Vous avez peut-être vu cette technique utilisée pour partager des connexions de base de données entre toutes les instances d'une classe de base de données. Ceci est fait car la création de la connexion à la base de données prend beaucoup de temps, il est donc préférable de n'en créer qu'une et de la partager (cela s'appelle un motif Singleton).
Des méthodes statiques (par exemple, public statique View :: format_phone_number ($ digits)) peuvent être utilisées SANS la première instanciation d’un de ces objets (c’est-à-dire qu’elles ne font pas référence à $ this).
Exemple de méthode statique:
public static function prettyName($first_name, $last_name)
{
echo ucfirst($first_name).' '.ucfirst($last_name);
}
echo Person::prettyName($derek->first_name, $derek->last_name);
Comme vous pouvez le constater, la fonction statique publique prettyName ne sait rien de l'objet. Il s'agit simplement de travailler avec les paramètres que vous transmettez, comme une fonction normale qui ne fait pas partie d'un objet. Pourquoi s'embêter, alors, si nous pouvions simplement l'avoir comme partie intégrante de l'objet?
SELF :: Si vous codez à l'extérieur de l'objet contenant la méthode statique à laquelle vous souhaitez faire référence, vous devez l'appeler. en utilisant le nom de l'objet View :: format_phone_number ($ phone_number); Si vous codez à l'intérieur de l'objet contenant la méthode statique à laquelle vous souhaitez faire référence, vous pouvez soit utilisez le nom de l'objet View :: format_phone_number ($ pn), OR, vous pouvez utiliser le raccourci self :: format_phone_number ($ pn)
Il en va de même pour les variables statiques: Exemple: View :: templates_path versus self :: templates_path
Dans la classe DB, si nous faisions référence à une méthode statique d'un autre objet, nous utiliserions le nom de l'objet: Exemple: Session :: getUsersOnline ();
Mais si la classe DB voulait se référer à sa propre variable statique, elle dirait simplement self: Exemple: self :: connection;
J'espère que ça aide à clarifier les choses :)
De cet article de blog :
self
fait référence à la classe actuelleself
peut être utilisé pour appeler des fonctions statiques et référencer des variables membres statiquesself
peut être utilisé dans des fonctions statiquesself
peut également désactiver le comportement polymorphe en contournant la vtable$this
fait référence à l'objet actuel$this
peut être utilisé pour appeler des fonctions statiques$this
ne doit pas être utilisé pour appeler des variables de membre statique. Utilisezself
à la place.$this
ne peut pas être utilisé à l'intérieur de fonctions statiques
En PHP, vous utilisez le mot-clé self pour accéder aux propriétés et méthodes statiques.
Le problème est que vous pouvez remplacer $this->method()
par self::method()
n'importe où, même si method()
est déclaré statique ou non. Alors lequel devriez-vous utiliser?
Considérons ce code:
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();
Dans cet exemple, self::who()
affichera toujours ‘parent’, tandis que $this->who()
dépendra de la classe de l’objet.
Nous pouvons maintenant voir que self fait référence à la classe dans laquelle il est appelé, tandis que $this
fait référence à classe de l'objet en cours.
Vous ne devez donc utiliser self que lorsque $this
n'est pas disponible ou lorsque vous ne souhaitez pas autoriser les classes descendantes à remplacer la méthode actuelle.
Dans une définition de classe, $ this fait référence à l'objet actuel, tandis que self fait référence à la classe actuelle.
Il est nécessaire de faire référence à un élément de classe à l'aide de self et à un élément d'objet à l'aide de $ this.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Voici un exemple d'utilisation correcte de $ this et self pour les variables de membre non statiques et statiques:
<?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();
?>
Selon http://www.php.net/manual/en/language.oop5.static.php il n'y a pas de $self
. Il n'y a que $this
, pour faire référence à l'instance actuelle de la classe (l'objet), et self, qui peut être utilisé pour faire référence à des membres statiques d'une classe. La différence entre une instance d'objet et une classe entre en jeu ici.
self
fait référence à la classe actuelle (dans laquelle elle est appelée),
$this
fait référence à l'objet actuel. Vous pouvez utiliser statique au lieu de soi. Voir l'exemple:
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();
Sortie: enfant parent
Je crois que la question n'était pas de savoir si vous pouvez appeler le membre statique de la classe en appelant ClassName::staticMember
. La question était quelle était la différence entre utiliser self::classmember
et $this->classmember
.
Par exemple, les deux exemples suivants fonctionnent sans erreur, que vous utilisiez self::
ou $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;
}
}
Comme personne ici n’a parlé de performances, voici un petit repère que j’ai fait (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
Ce sont les résultats pour 2 000 000 courses, et voici le code que j'ai utilisé:
<?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();
Voir l'exemple suivant qui montre la surcharge.
<?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 plupart du temps, vous voulez faire référence à la classe actuelle, raison pour laquelle vous utilisez static
ou $this
. Cependant, il y a des moments où vous besoinself
parce que vous voulez la classe d'origine quelle que soit son extension. (Très, très rarement)
Lorsque self
est utilisé avec l'opérateur ::
, il fait référence à la classe actuelle, ce qui peut être fait à la fois dans des contextes statiques et non statiques. $this
fait référence à l'objet lui-même. De plus, il est parfaitement légal d'utiliser $this
pour appeler des méthodes statiques (mais pas pour faire référence à des champs).
$this
se réfère à l'objet de la classe en cours, self
se réfère à la classe en cours (Not object). La classe est le modèle de l'objet. Donc, vous définissez une classe, mais vous construisez des objets.
Donc, en d'autres termes, utilisez self for static
et this for none-static members or methods
.
également dans le scénario enfant/parent self / parent
est principalement utilisé pour identifier les membres et méthodes de la classe enfant et parent.
De plus, puisque $this::
n'a pas encore été discuté.
À titre informatif uniquement, à partir de PHP 5.3 lorsque vous utilisez des objets instanciés pour obtenir la valeur de la portée actuelle, par opposition à static::
, vous pouvez également utiliser $this::
de cette manière.
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'utilisation du code ci-dessus n'est pas une pratique courante ou recommandée, mais simplement pour illustrer son utilisation, et consiste plutôt à agir comme un "Le saviez-vous?" en référence à la question de l'affiche originale.
Il représente également l'utilisation de $object::CONSTANT
par exemple echo $foo::NAME;
par opposition à $this::NAME;
J'ai rencontré la même question et la réponse simple est:
Chaque fois que vous utilisez méthodes statiques ou attributs statiques et que vous souhaitez les appeler sans qu'un objet de la classe ne soit instancié, vous devez utiliser self :: pour les appeler, car $ this nécessite toujours que l'objet soit créé.
Utilisez self
si vous souhaitez appeler une méthode d'une classe sans créer un objet/une instance de cette classe, économisez ainsi RAM (utilisez parfois self à cette fin). En d'autres termes, il appelle en fait une méthode de manière statique. Utilisez this
pour la perspective d'objet.
Cas 1: Utiliser self
peut être utilisé pour les constantes de classe
class classA { const FIXED_NUMBER = 4; self :: POUNDS_TO_KILOGRAMS }
Si vous voulez l'appeler en dehors de la classe, utilisez classA::POUNDS_TO_KILOGRAMS
pour accéder aux constantes.
Cas 2: Pour les propriétés statiques
class classC { fonction publique __construct () { self :: $ _ counter ++; $ this-> num = self :: $ _ counter; } }
Selon php.net, il existe trois mots-clés spéciaux dans ce contexte: self
, parent
et static
. Ils sont utilisés pour accéder aux propriétés ou aux méthodes depuis la définition de la classe.
$this
, d'autre part, est utilisé pour appeler une instance et des méthodes de n'importe quelle classe tant que cette classe est accessible.