oop $this-> - Qu'est-ce que la variable $ this signifie en PHP?




donnée sondage (9)

La meilleure façon d'en savoir plus sur la variable $this php est de demander à PHP ce que c'est. Ne nous demandez pas, demandez au compilateur:

print gettype($this);            //object
print get_object_vars($this);    //Array
print is_array($this);           //false
print is_object($this);          //true
print_r($this);                  //dump of the objects inside it
print count($this);              //true
print get_class($this);          //YourProject\YourFile\YourClass
print isset($this);              //true
print get_parent_class($this);   //YourBundle\YourStuff\YourParentClass
print gettype($this->container); //object

Je vois la variable $this en PHP tout le temps et je ne sais pas à quoi ça sert. Je ne l'ai jamais utilisé personnellement, et les moteurs de recherche ignorent le $ et je me retrouve avec une recherche pour le mot "ceci".

Quelqu'un peut-il me dire comment la variable $ cela fonctionne en PHP?


Lorsque vous créez une classe, vous avez (dans de nombreux cas) des variables d'instance et des méthodes (aka .fonctions). $ this accède à ces variables d'instance afin que vos fonctions puissent prendre ces variables et faire ce dont elles ont besoin pour faire ce que vous voulez avec elles.

une autre version de l'exemple de meder:

class Person {

    protected $name;  //can't be accessed from outside the class

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}
// this line creates an instance of the class Person setting "Jack" as $name.  
// __construct() gets executed when you declare it within the class.
$jack = new Person("Jack"); 

echo $jack->getName();

Output:

Jack

$ ceci est une variable spéciale et fait référence au même objet ie. lui-même.

il fait référence à l'instance de la classe actuelle

Voici un exemple qui va effacer la déclaration ci-dessus

<?php
 class Books {
  /* Member variables */
  var $price;
  var $title;

  /* Member functions */
  function setPrice($par){
     $this->price = $par;
  }

  function getPrice(){
     echo $this->price ."<br/>";
  }

  function setTitle($par){
     $this->title = $par;
  }

  function getTitle(){
     echo $this->title ." <br/>";
  }
}
?> 

Je connais sa vieille question, de toute façon une autre explication exacte à propos de ceci . $ ceci est principalement utilisé pour référencer les propriétés d'une classe.

Exemple:

Class A
{
   public $myname;    //this is a member variable of this class

function callme() {
    $myname = 'function variable';
    $this->myname = 'Member variable';
    echo $myname;                  //prints function variable
    echo $this->myname;              //prints member variable
   }
}

sortie:

function variable

member variable


C'est le moyen de référencer une instance d'une classe depuis l'intérieur de lui-même, comme de nombreux autres langages orientés objet.

À partir des documents PHP :

La pseudo-variable $ this est disponible lorsqu'une méthode est appelée depuis un contexte d'objet. $ ceci est une référence à l'objet appelant (généralement l'objet auquel appartient la méthode, mais éventuellement un autre objet, si la méthode est appelée de manière statique dans le contexte d'un objet secondaire).


Voyons ce qui se passe si nous n'utilisons pas $ this et essayons d'avoir des variables d'instance et des arguments constructeurs portant le même nom avec l'extrait de code suivant

<?php

class Student {
    public $name;

    function __construct( $name ) {
        $name = $name;
    }
};

$tom = new Student('Tom');
echo $tom->name;

?>

Cela ne résonne rien mais

<?php

class Student {
    public $name;

    function __construct( $name ) {
        $this->name = $name; // Using 'this' to access the student's name
    }
};

$tom = new Student('Tom');
echo $tom->name;

?>

cela fait écho à "Tom"


$this est une référence à l'objet appelant (généralement l'objet auquel appartient la méthode, mais éventuellement un autre objet, si la méthode est appelée de manière statique dans le contexte d'un objet secondaire).


Que sont les métaclasses? A quoi les utilisez-vous?

TLDR: une métaclasse instancie et définit le comportement d'une classe de la même manière qu'une classe instancie et définit le comportement d'une instance.

Pseudocode:

>>> Class(...)
instance

Ce qui précède devrait avoir l'air familier. Eh bien, d'où vient la Class ? C'est une instance d'une métaclasse (également un pseudocode):

>>> Metaclass(...)
Class

En code réel, nous pouvons passer la métaclasse par défaut, type , tout ce dont nous avons besoin pour instancier une classe et nous obtenons une classe:

>>> type('Foo', (object,), {}) # requires a name, bases, and a namespace
<class '__main__.Foo'>

En d'autres termes

  • Une classe est à une instance comme une métaclasse est à une classe.

    Lorsque nous instancions un objet, nous obtenons une instance:

    >>> object()                          # instantiation of class
    <object object at 0x7f9069b4e0b0>     # instance
    

    De même, lorsque nous définissons explicitement une classe avec la métaclasse par défaut, type , nous l'instancions:

    >>> type('Object', (object,), {})     # instantiation of metaclass
    <class '__main__.Object'>             # instance
    
  • En d'autres termes, une classe est une instance d'une métaclasse:

    >>> isinstance(object, type)
    True
    
  • En d'autres termes, une métaclasse est une classe.

    >>> type(object) == type
    True
    >>> object.__class__
    <class 'type'>
    

Lorsque vous écrivez une définition de classe et que Python l'exécute, il utilise une métaclasse pour instancier l'objet de classe (qui, à son tour, sera utilisé pour instancier des instances de cette classe).

Tout comme nous pouvons utiliser les définitions de classe pour modifier le comportement des instances d'objet personnalisé, nous pouvons utiliser une définition de classe de métaclasse pour modifier le comportement d'un objet de classe.

Que peuvent-ils être utilisés? De la docs :

Les utilisations potentielles des métaclasses sont illimitées. Parmi les idées explorées figurent la journalisation, la vérification des interfaces, la délégation automatique, la création automatique de propriétés, les mandataires, les infrastructures et le verrouillage / synchronisation automatique des ressources.

Néanmoins, il est généralement recommandé aux utilisateurs d’éviter d’utiliser des métaclasses, sauf en cas de nécessité absolue.

Vous utilisez une métaclasse chaque fois que vous créez une classe:

Lorsque vous écrivez une définition de classe, par exemple, comme ceci,

class Foo(object): 
    'demo'

Vous instanciez un objet de classe.

>>> Foo
<class '__main__.Foo'>
>>> isinstance(Foo, type), isinstance(Foo, object)
(True, True)

Cela revient à appeler un type fonctionnellement avec les arguments appropriés et à assigner le résultat à une variable de ce nom:

name = 'Foo'
bases = (object,)
namespace = {'__doc__': 'demo'}
Foo = type(name, bases, namespace)

Notez que certaines choses sont automatiquement ajoutées à __dict__ , c'est-à-dire l'espace de nom:

>>> Foo.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'Foo' objects>, 
'__module__': '__main__', '__weakref__': <attribute '__weakref__' 
of 'Foo' objects>, '__doc__': 'demo'})

La métaclasse de l'objet créé, dans les deux cas, est le type .

(Une note de côté sur le contenu de la classe __dict__ : __module__ est présente car les classes doivent savoir où elles sont définies, et __dict__ et __weakref__ sont présentes car nous ne définissons pas __slots__ . espace dans les instances, car nous pouvons interdire __dict__ et __weakref__ en les excluant, par exemple:

>>> Baz = type('Bar', (object,), {'__doc__': 'demo', '__slots__': ()})
>>> Baz.__dict__
mappingproxy({'__doc__': 'demo', '__slots__': (), '__module__': '__main__'})

... mais je m'égare.)

Nous pouvons étendre le type comme n'importe quelle autre définition de classe:

Voici le __repr__ par défaut des classes:

>>> Foo
<class '__main__.Foo'>

L'une des choses les plus utiles que nous puissions faire par défaut en écrivant un objet Python est de lui fournir un bon __repr__ . Lorsque nous appelons help(repr) nous apprenons qu'il existe un bon test pour un __repr__ qui requiert également un test d'égalité - obj == eval(repr(obj)) . L'implémentation simple suivante de __repr__ et __eq__ pour les instances de classe de notre classe type nous fournit une démonstration susceptible d'améliorer la valeur par défaut __repr__ des classes:

class Type(type):
    def __repr__(cls):
        """
        >>> Baz
        Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
        >>> eval(repr(Baz))
        Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
        """
        metaname = type(cls).__name__
        name = cls.__name__
        parents = ', '.join(b.__name__ for b in cls.__bases__)
        if parents:
            parents += ','
        namespace = ', '.join(': '.join(
          (repr(k), repr(v) if not isinstance(v, type) else v.__name__))
               for k, v in cls.__dict__.items())
        return '{0}(\'{1}\', ({2}), {{{3}}})'.format(metaname, name, parents, namespace)
    def __eq__(cls, other):
        """
        >>> Baz == eval(repr(Baz))
        True            
        """
        return (cls.__name__, cls.__bases__, cls.__dict__) == (
                other.__name__, other.__bases__, other.__dict__)

Alors maintenant, lorsque nous créons un objet avec cette métaclasse, l' __repr__écho sur la ligne de commande fournit une vision beaucoup moins laide que celle par défaut:

>>> class Bar(object): pass
>>> Baz = Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
>>> Baz
Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})

Avec une belle __repr__définition pour l'instance de classe, nous avons une capacité plus grande de déboguer notre code. Cependant, il eval(repr(Class))est peu probable que des vérifications supplémentaires soient effectuées (car les fonctions seraient plutôt impossibles à évaluer depuis leurs valeurs par défaut __repr__).

Une utilisation attendue: __prepare__un espace de noms

Si, par exemple, nous voulons savoir dans quel ordre les méthodes d'une classe sont créées, nous pourrions fournir un dict ordonné en tant qu'espace de nom de la classe. Nous ferions ceci avec __prepare__qui renvoie le dict d'espace de noms pour la classe si elle est implémentée dans Python 3 :

from collections import OrderedDict

class OrderedType(Type):
    @classmethod
    def __prepare__(metacls, name, bases, **kwargs):
        return OrderedDict()
    def __new__(cls, name, bases, namespace, **kwargs):
        result = Type.__new__(cls, name, bases, dict(namespace))
        result.members = tuple(namespace)
        return result

Et utilisation:

class OrderedMethodsObject(object, metaclass=OrderedType):
    def method1(self): pass
    def method2(self): pass
    def method3(self): pass
    def method4(self): pass

Et maintenant nous avons un enregistrement de l'ordre dans lequel ces méthodes (et autres attributs de classe) ont été créés:

>>> OrderedMethodsObject.members
('__module__', '__qualname__', 'method1', 'method2', 'method3', 'method4')

Notez que cet exemple a été adapté à partir de la docs - le nouvel enum de la bibliothèque standard le fait.

Nous avons donc instancié une métaclasse en créant une classe. Nous pouvons également traiter la métaclasse comme n'importe quelle autre classe. Il a un ordre de résolution de méthode:

>>> inspect.getmro(OrderedType)
(<class '__main__.OrderedType'>, <class '__main__.Type'>, <class 'type'>, <class 'object'>)

Et il a approximativement le correct repr(que nous ne pouvons plus évaluer si nous ne pouvons pas trouver un moyen de représenter nos fonctions.):

>>> OrderedMethodsObject
OrderedType('OrderedMethodsObject', (object,), {'method1': <function OrderedMethodsObject.method1 at 0x0000000002DB01E0>, 'members': ('__module__', '__qualname__', 'method1', 'method2', 'method3', 'method4'), 'method3': <function OrderedMet
hodsObject.method3 at 0x0000000002DB02F0>, 'method2': <function OrderedMethodsObject.method2 at 0x0000000002DB0268>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'OrderedMethodsObject' objects>, '__doc__': None, '__d
ict__': <attribute '__dict__' of 'OrderedMethodsObject' objects>, 'method4': <function OrderedMethodsObject.method4 at 0x0000000002DB0378>})




php oop this