En PHP 5, quelle est la différence entre utiliser self
et $this
?
Quand est-ce approprié?
En PHP 5, quelle est la différence entre utiliser self
et $this
?
Quand est-ce approprié?
Réponses:
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 $this
et self
pour les variables membres 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 les variables membres 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 à l'aide self
de 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 d'
$this->foo()
appeler lafoo()
fonction membre 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é.
Depuis http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Par http://board.phpbuilder.com/member.php?145249-laserlight
self
est utilisé avec l'opérateur de résolution de portée ::
pour faire référence à la classe actuelle; cela peut être fait à la fois dans des contextes statiques et non statiques. De plus, il est parfaitement légal d'utiliser $this
pour appeler des méthodes statiques (mais pas pour référencer des champs).
$this::
?
Le mot-clé self ne fait PAS 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 wiki sur vtable ) pour l'objet actuel. Tout comme vous pouvez utiliser parent::methodName()
pour appeler la version parent d'une fonction, vous pouvez également appeler self::methodName()
pour appeler l'implémentation de classes actuelle 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 $this
pointeur, donc la vtable est invoquée pour appeler Geek::getTitle()
.
sayGoodbye()
utilise self::getTitle()
, donc la vtable n'est pas utilisée et Person::getTitle()
est appelée. Dans les deux cas, nous avons affaire à la méthode d'un objet instancié, et avons accès au $this
pointeur dans les fonctions appelées.
self
se trouve" / "la définition de classe, elle fait littéralement partie de" ainsi que "la classe de l'objet" (qui serait en fait static
).
$this::
?
$this::
; tous les cas possibles sont déjà couverts par des syntaxes plus couramment utilisées. Selon ce que vous voulez dire, l' utilisation $this->
, self::
ou static::
.
NE PAS UTILISER self::
, utiliserstatic::
Il y a un autre aspect de self :: qui mérite d'être mentionné. Désagréablement self::
fait référence à la portée au point de définition et non au point d'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 vivante". Considérez maintenant ce qui se passe lorsque nous créons 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», mais ce que nous voyons est «La personne est vivante», car la portée contient la définition de la méthode d'origine lorsque l'appel à a self::getStatus()
été défini.
PHP 5.3 a une solution. L' static::
opérateur de résolution implémente la "liaison statique tardive", ce qui est une façon élégante de dire qu'elle est liée à la portée de la classe appelée. Modifiez la ligne status()
pour static::getStatus()
et les résultats sont ce que vous attendez. Dans les anciennes versions de PHP, vous devrez trouver un kludge pour ce faire.
Voir la documentation PHP
Donc, pour répondre à la question pas comme demandé ...
$this->
fait référence à l'objet courant (une instance d'une classe), tandis que static::
fait référence à une classe
getStatus
méthode comme celle que j'appellerais pour une instance de classe, pas pour une classe.
self::
, vous pouvez l'obtenir, moins prêter à confusion, en utilisant le nom de classe spécifique, par exemple MyClass::
.
Pour vraiment comprendre de quoi nous parlons lorsque nous parlons de self
versus $this
, nous devons réellement creuser ce qui se passe au niveau conceptuel et pratique. Je ne pense pas que l'une des réponses le fasse correctement, alors voici ma tentative.
Commençons par parler de ce qu'est une classe et un objet .
Alors, qu'est - ce qu'une classe ? Beaucoup de gens le définissent comme un plan directeur ou un modèle pour un objet. En fait, vous pouvez en savoir plus sur les classes en 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 y a une propriété sur cette classe appelée $name
et une méthode (fonction) appelée sayHello()
.
Il est très important 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 partout où vous la regardez.
Un objet d'autre part est ce qu'on appelle une instance d'une classe. Cela signifie que nous prenons le «plan directeur» de la classe et que nous l'utilisons pour faire une copie dynamique. Cette copie est désormais spécifiquement liée à la variable dans laquelle elle est stockée. Par conséquent, toute modification apportée à une instance est locale à 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 en utilisant l' new
opérateur.
Par conséquent, nous disons qu'une classe est une structure globale et un objet est une structure locale. Ne vous inquiétez pas de cette drôle de ->
syntaxe, nous allons y revenir un peu.
Une autre chose dont nous devrions parler, c'est que nous pouvons vérifier si une instance est une instanceof
classe particulière: $bob instanceof Person
qui retourne un booléen si l' $bob
instance a été créée en utilisant la Person
classe, ou un enfant de Person
.
Examinons donc un peu ce que contient réellement 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 - Ce sont des fonctions que chaque instance contiendra (et fonctionnera sur les instances).
class Foo {
public function bar() {}
}
Méthodes statiques - Ce sont des fonctions qui sont partagées dans toute la classe. Ils ne fonctionnent pas 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 l' électricité statique qui identifient si les informations sont partagées (et donc statiques) ou non (et donc dynamiques).
A l'intérieur d'une méthode, l'instance d'un objet est représentée par la $this
variable. L'état actuel de cet objet est là, et la mutation (modification) de toute propriété entraînera une modification de cette instance (mais pas des autres).
Si une méthode est appelée statiquement, la $this
variable n'est pas définie . En effet, aucune instance n'est associée à un appel statique.
La chose intéressante ici est de savoir comment les appels statiques sont effectués. Parlons donc de la façon dont nous accédons à l'État:
Alors maintenant que nous avons enregistré cet état, nous devons y accéder. Cela peut devenir un peu délicat (ou bien plus qu'un peu), alors divisons cela en deux points de vue: de l'extérieur d'une instance / classe (disons à 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).
De l'extérieur d'une instance / classe, nos règles sont assez simples et prévisibles. Nous avons deux opérateurs, et chacun nous dit immédiatement si nous avons affaire à une instance ou à une classe statique:
->
- objet-opérateur - Ceci est toujours utilisé lorsque nous accédons à une instance.
$bob = new Person;
echo $bob->name;
Il est important de noter que l'appel Person->foo
n'a pas de sens (puisqu'il Person
s'agit d'une classe et non d'une instance). Par conséquent, c'est une erreur d'analyse.
::
- scope-resolution-operator - Ceci est toujours utilisé pour accéder à une propriété ou une méthode statique de classe.
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 extrêmement important de noter que lorsque nous faisons cela de l'extérieur , l'instance de l'objet est masquée de la bar()
méthode. Cela signifie que c'est exactement la même chose que la course:
$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 nettement floue.
L' opérateur d'objet ->
est toujours utilisé pour effectuer des appels à l'état d'instance de l'objet.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
L'appel de la bar()
méthode sur $foo
(une instance de Foo
) à l'aide de l'opérateur objet: $foo->bar()
entraînera la version de l'instance de $a
.
Voilà donc ce que nous attendons.
La signification de l' ::
opérateur change cependant. Cela dépend du contexte de l'appel à la fonction courante:
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 Foo::bar()
appellera la baz()
méthode de manière statique et ne$this
sera donc pas rempli. Il convient de noter que dans les versions récentes de PHP (5.3+), cela déclenchera une E_STRICT
erreur, car nous appelons des méthodes non statiques de manière statique.
Dans un contexte d'instance
Dans un contexte d'instance, en revanche, 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
, alors elle utilisera un appel statique. Si ce n'est pas le cas, il transmettra les informations d'instance.
Ainsi, en regardant le code ci-dessus, l'appel $foo->bar()
reviendra true
, car l'appel "statique" se produit à l'intérieur d'un contexte d'instance.
Ça a du sens? Je ne le pensais pas. C'est confu.
Parce que tout lier ensemble 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 la portée.
self
- Cela fait référence au nom de classe actuel. C'est self::baz()
la même chose que Foo::baz()
dans la Foo
classe (n'importe quelle méthode).
parent
- Cela fait référence au parent de la classe actuelle.
static
- Il s'agit de la classe appelée. Grâce à l'héritage, les classes enfants peuvent remplacer les méthodes et les propriétés statiques. Ainsi, les appeler à l'aide static
d'un nom de classe nous permet de déterminer d'où vient l'appel, plutôt que le niveau actuel.
La façon la plus simple de comprendre cela est de commencer à regarder quelques exemples. Choisissons une classe:
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. Ignorez 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 (parce que nous l'utilisons self
pour y accéder. Si nous l'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 d' Person::getName()
instance à chaque fois. Mais nous utilisons le parent::getName()
pour le faire dans l'un des cas (le cas des enfants). 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 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 celle $this
qui est transmise à la Foo::isFoo()
méthode est l'instance de $bar
.
Cela peut provoquer toutes sortes de bugs et WTF-ery conceptuel. Donc , je suggère fortement d' éviter l' ::
opérateur à partir de méthodes d'instance sur quoi que ce soit , sauf ces trois mots - clés « raccourci » virtuels ( static
, self
et parent
).
Notez que les méthodes et propriétés statiques sont partagées par tous. Cela en fait essentiellement des variables globales. Avec tous les mêmes problèmes que les globaux. 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 qu'elles soient vraiment globales.
En général, vous voudrez utiliser ce que l'on appelle la liaison statique tardive en utilisant static
au lieu de self
. Mais notez que ce n'est pas la même chose, donc dire "toujours utiliser à la static
place de self
est vraiment à courte vue. Au lieu de cela, arrêtez-vous et pensez à l'appel que vous voulez faire et pensez si vous voulez que les classes enfants soient capables de remplacer cette résolution statique appel.
Dommage, revenez en arrière et lisez-le. C'est peut-être trop long, mais c'est aussi long car 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ù as $this
fait référence à l' instance d' objet actuelle . Notez qu'il self
s'agit d'un raccourci copier / coller. Vous pouvez le remplacer en toute sécurité par le nom de votre classe, et cela fonctionnera bien. Mais $this
c'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 objet est utilisé ( ->
), alors vous savez toujours que vous avez affaire à une instance. Si l'opérateur scope-resolution-operator est utilisé ( ::
), vous avez besoin de plus d'informations sur le contexte (sommes-nous déjà dans un contexte d'objet? Sommes-nous en dehors d'un objet? Etc).
$this
ne sera pas défini si vous suivez les "normes strictes" et n'appelez pas de méthodes statiques qui ne sont pas définies comme statiques. Je vois le résultat que vous avez expliqué ici: 3v4l.org/WeHVM D'accord, vraiment bizarre.
Foo::isFoo()
on l'appelle statiquement, $this
ne sera pas défini. C'est un comportement plus intuitif à mon avis. - Un autre résultat différent est donné s'il Bar
devait s'étendre de Foo
. Ensuite, l'appel Foo::isFoo()
serait en fait dans le contexte de l'instance (non spécifique à PHP7).
self
(pas $ self) fait référence au type de classe, où as $this
fait référence à l' instance actuelle de la classe. self
est à utiliser dans les fonctions membres statiques pour vous permettre d'accéder aux variables membres statiques. $this
est utilisé dans les fonctions membres non statiques et est une référence à l'instance de la classe sur laquelle la fonction membre a été appelée.
Parce que this
c'est un objet, vous l'utilisez comme:$this->member
Parce que ce self
n'est pas un objet, c'est fondamentalement un type qui fait automatiquement référence à la classe actuelle, vous l'utilisez comme:self::member
$this->
est utilisé pour faire référence à une instance spécifique des variables d'une classe (variables membres) ou des méthodes.
Example:
$derek = new Person();
$ derek est maintenant une instance spécifique de Person. Chaque personne a un prénom et un nom de famille, mais $ derek a un prénom et un nom de famille spécifiques (Derek Martin). Dans l'instance $ derek, nous pouvons les désigner comme $ this-> first_name et $ this-> last_name
ClassName :: est utilisé pour faire référence à ce type de classe, et à ses variables statiques, aux méthodes statiques. Si cela peut vous aider, vous pouvez mentalement remplacer 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 (ie 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 (connexion $ statique).
Variables statiques Exemple: Imaginez 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, cela augmentera notre compteur de connexions d'une unité. Chaque fois que nous détruisons ou cessons d'utiliser une instance, cela diminue le compteur de connexions d'une unité. De cette façon, nous pouvons surveiller le nombre d'instances de l'objet de base de données que nous utilisons avec:
echo DB::num_connections;
Parce que $ 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. Cela est dû au fait que la création de la connexion à la base de données prend beaucoup de temps, il est donc préférable d'en créer une seule et de la partager (c'est ce qu'on appelle un modèle Singleton).
Les méthodes statiques (c'est-à-dire View :: format_phone_number ($ digits) statiques publiques) peuvent être utilisées SANS d'abord instancier l'un de ces objets (c'est-à-dire qu'elles ne se réfèrent pas en interne à $ 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 voir, la fonction statique publique prettyName ne sait rien de l'objet. Cela fonctionne simplement 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 ne pas l'avoir comme partie de l'objet?
SELF :: Si vous codez en dehors de l'objet qui a la méthode statique à laquelle vous voulez vous référer, 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 qui a la méthode statique à laquelle vous voulez vous référer, vous pouvez soit utiliser le nom de l'objet View :: format_phone_number ($ pn), OU 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 faire référence à sa propre variable statique, elle dirait juste self: Exemple: self :: connection;
J'espère que cela aide à clarifier les choses :)
$
signe. Par exempleself::$templates_path
De ce billet de blog :
self
fait référence à la classe actuelleself
peut être utilisé pour appeler des fonctions statiques et référencer des variables de membres statiquesself
peut être utilisé à l'intérieur de fonctions statiquesself
peut également désactiver le comportement polymorphe en contournant le vtable$this
fait référence à l'objet courant$this
peut être utilisé pour appeler des fonctions statiques$this
ne doit pas être utilisé pour appeler des variables de membre statiques. Utilisezself
plutôt.$this
ne peut pas être utilisé dans des 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ù, quel que soit le cas method()
est déclarée statique ou non. Alors, lequel devez-vous utiliser?
Considérez 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.
Maintenant, nous pouvons voir que self fait référence à la classe dans laquelle il est appelé, tandis que se $this
réfère à la classe de l'objet courant .
Par conséquent, vous ne devez utiliser self que lorsqu'il $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 en utilisant self
et de faire référence à un élément d'objet en utilisant $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 membres 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 en a pas $self
. Il n'y a $this
, pour faire référence à l'instance actuelle de la classe (l'objet), et self, qui peuvent être utilisés pour faire référence aux membres statiques d'une classe. La différence entre une instance d'objet et une classe entre en jeu ici.
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 est 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;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
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 self. 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: parent enfant
$this
vers fait référence à l'objet actuel.static
fait référence à l'objet actuel.self
fait référence à la classe exacte dans laquelle elle a été définie.parent
fait référence au parent de la classe exacte dans laquelle elle a été définie.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 vous référer à la classe actuelle, c'est pourquoi vous utilisez static
ou $this
. Cependant, il y a des moments où vous en avez besoin self
parce que vous voulez la classe d'origine indépendamment de ce qui la prolonge. (Très, très rarement)
Comme personne ici n'a parlé de performances, voici un petit benchmark 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 de runs, 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();
1 / 2e9 s = 0.5 ns
ces jours-ci
use
mot - clé tbh, mais je n'ai plus PHP pour refaire un benchmark, et je n'ai pas vraiment envie de le réinstaller.
Lorsqu'il 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).
Je suis tombé sur la même question et la réponse simple est:
$this
nécessite une instance de la classeself::
neChaque fois que vous utilisez des méthodes statiques ou des attributs statiques et que vous souhaitez les appeler sans avoir un objet de la classe instancié, vous devez les utiliser self:
pour les appeler, car $this
il faut toujours créer un objet.
$this
fait référence à l'objet de classe actuel, self
fait référence à la classe actuelle (pas d'objet). La classe est le plan directeur de l'objet. Vous définissez donc une classe, mais vous construisez des objets.
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 les méthodes de la classe enfant et parent.
De plus, depuis $this::
n'a pas encore été discuté.
À titre informatif uniquement, à partir de PHP 5.3 lorsque vous traitez avec des objets instanciés pour obtenir la valeur de portée actuelle, par opposition à l'utilisation static::
, vous pouvez également l'utiliser $this::
comme tel.
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 vise simplement à illustrer son utilisation et consiste à agir davantage comme un "Le saviez-vous?" en référence à la question de l'affiche originale.
Il représente également l'utilisation $object::CONSTANT
par exemple echo $foo::NAME;
de$this::NAME;
À utiliser self
si vous souhaitez appeler une méthode d'une classe sans créer d'objet / instance de cette classe, économisant ainsi de la RAM (utilisez parfois self à cet effet). En d'autres termes, il appelle en fait une méthode de manière statique. À utiliser this
pour la perspective d'objet.
Cas 1: l'utilisation self
peut être utilisée pour les constantes de classe
classe 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 y a trois mots - clés spécifiques dans ce contexte: self
, parent
et static
. Ils sont utilisés pour accéder aux propriétés ou méthodes de l'intérieur de la définition de 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.
mot-clé self :: utilisé pour la classe actuelle et utilisé pour accéder aux membres statiques, aux méthodes et aux constantes. Mais dans le cas de $ this, vous ne pouvez pas appeler le membre statique, la méthode et les fonctions.
Vous pouvez utiliser le mot-clé self :: dans une autre classe et accéder aux membres statiques, à la méthode et aux constantes. Quand il sera étendu de la classe parente et même en cas de $ this mot - clé. Vous pouvez accéder aux membres non statiques, à la méthode et à la fonction dans une autre classe lorsqu'elle sera étendue à partir de la classe parente.
Le code donné ci-dessous est un exemple de self :: et $ this mot - clé. Copiez et collez simplement le code dans votre fichier de code et voyez le résultat.
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());