166 votes

Quelle est la différence entre self::$bar et static::$bar en PHP ?

Quelle est la différence entre utiliser self y static dans l'exemple ci-dessous ?

class Foo
{
    protected static $bar = 1234;

    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }

}

Foo::instance();

produit

1234
1234

228voto

BoltClock Points 249668

Lorsque vous utilisez self pour faire référence à un membre de classe, vous faites référence à la classe dans laquelle vous utilisez le mot-clé. Dans ce cas, votre Foo définit une propriété statique protégée appelée $bar . Lorsque vous utilisez self dans le Foo pour faire référence à la propriété, vous faites référence à la même classe.

Par conséquent, si vous essayez d'utiliser self::$bar ailleurs dans votre Foo mais vous aviez un Bar avec une valeur différente pour la propriété, il utiliserait la classe Foo::$bar au lieu de Bar::$bar ce qui n'est peut-être pas votre intention :

class Foo
{
    protected static $bar = 1234;
}

class Bar extends Foo
{
    protected static $bar = 4321;
}

Quand vous appelez une méthode via static vous invoquez une fonction appelée liaisons statiques tardives (introduit en PHP 5.3).

Dans le scénario ci-dessus, l'utilisation de self aura pour résultat Foo::$bar (1234). Et en utilisant static aura pour résultat Bar::$bar (4321) car avec static l'interpréteur prend en compte la redéclaration dans le fichier Bar pendant l'exécution.

// self
var_dump(Foo::$bar);
// (int) 1234

// static
var_dump(Bar::$bar);
// (int) 4321

Vous utilisez généralement les liaisons statiques tardives pour les méthodes ou même la classe elle-même, plutôt que pour les propriétés, car vous ne redéclarez pas souvent les propriétés dans les sous-classes ; un exemple d'utilisation de l'option static pour l'invocation d'un constructeur tardif se trouve dans cette question connexe : Nouveau soi vs. nouveau statique

Cependant, cela n'empêche pas d'utiliser static avec des propriétés également.

24voto

Jsowa Points 4130

J'ai un petit exemple montrant la différence entre self y static . Utilisation de static:: effectue une liaison statique tardive et lie ainsi la valeur de la variable de la classe enfant.

class A { // Base Class
    protected static $name = 'ClassA';
    public static function getSelfName() {
        return self::$name;
    }
    public static function getStaticName() {
        return static::$name;
    }
}

class B extends A {
    protected static $name = 'ClassB';
}

echo B::getSelfName(); // ClassA
echo B::getStaticName(); // ClassB

21voto

Steve Bauman Points 2511

Avec self appeler :

class Phone
{
    protected static $number = 123;

    public function getNumber()
    {
        return self::$number;
    }
}

class Fax extends Phone
{
    protected static $number = 234;
}

// Displays: "123"
echo (new Fax)->getNumber();

Vous pouvez voir ci-dessus que, même si nous avons remplacé l'option $number avec notre Fax classe, getNumber() revient toujours 123 .

Ceci parce que nous avons demandé à PHP de nous donner la variable où elle a été définie dans -- ce qui retournera Phone à la place.

Si nous échangeons le self appeler avec static nous obtiendrons Fax à la place :

Avec static appeler :

class Phone
{
    protected static $number = 123;

    public function getNumber()
    {
        return static::$number;
    }
}

class Fax extends Phone
{
    protected static $number = 234;
}

// Displays: "234"
echo (new Fax)->getVar();

8voto

Minty Stark Points 19

Comme nous l'avons mentionné, l'une des principales différences est que static permet des liaisons statiques tardives. L'un des scénarios les plus utiles que j'ai trouvé est la création de classes de base pour les classes singleton :

class A { // Base Class
    protected static $name = '';
    protected static function getName() {
        return static::$name;
    }
}
class B extends A {
    protected static $name = 'MyCustomNameB';
}
class C extends A {
    protected static $name = 'MyCustomNameC';
}

echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC

Utilisation de return static::$name dans la classe de base renverra ce qui était attaché statiquement lorsqu'elle a été étendue. Si vous deviez utiliser return self::$name puis B::getName() renvoie une chaîne vide, car c'est ce qui est déclaré dans la classe Base.

6voto

dwoutsourcing Points 37

Peut-être que ce code auto-explicatif vous aidera :

class Foo 
{
    protected static $bar = 'parent value';

    public static function test() 
    {
        var_dump('I am your father');
        var_dump('self:: here means '.self::$bar);
        var_dump('static:: here means '.static::$bar);
    }
}

class Bar extends Foo 
{
    protected static $bar = 'child value';

    public static function test() 
    {
        parent::Test();

        var_dump('I am the child');
        var_dump('self:: here means '.self::$bar);
        var_dump('static:: here means '.static::$bar);
    }
}

Bar::test();
Foo::test();

Cela produit le résultat suivant (j'ai ajouté des sauts de ligne pour plus de clarté) :

'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means child value' (length=31)

'I am the child' (length=14)
'self:: here means child value' (length=29)
'static:: here means child value' (length=31)

'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means parent value' (length=32)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X