Sostituzione delle costanti di classe rispetto alle proprietà


99

Vorrei capire meglio perché, nello scenario seguente, c'è una differenza nel modo in cui le costanti di classe vengono ereditate rispetto alle variabili di istanza.

<?php
class ParentClass {
    const TEST = "ONE";
    protected $test = "ONE";

    public function showTest(){
        echo self::TEST;
        echo $this->test;
    }
}

class ChildClass extends ParentClass {
    const TEST = "TWO";
    protected $test = "TWO";

    public function myTest(){
        echo self::TEST;
        echo $this->test;
    }
}

$child = new ChildClass();
$child->myTest();
$child->showTest();

Produzione:

TWO
TWO
ONE
TWO

Nel codice precedente, ChildClass non ha un metodo showTest (), quindi il metodo ParentClass showTest () viene utilizzato per ereditarietà. I risultati mostrano che poiché il metodo è in esecuzione su ParentClass, viene valutata la versione ParentClass della costante TEST, mentre poiché sta valutando all'interno del contesto ChildClass tramite ereditarietà, viene valutata la variabile membro ChildClass $ test.

Ho letto la documentazione, ma non riesco a vedere alcuna menzione di questa sfumatura. Qualcuno può farmi luce?


WTF? Override costante !? Non farlo! mai!
qwert_ukg

2
@qwert_ukg Indeed. Qualcuno dovrebbe comunicarlo agli sviluppatori di PHP. O almeno consenti final...
Luke Sawczak

1
Ci sono sicuramente casi d'uso abbastanza buoni anche per l'override costante:]
Arziel

Risposte:


194

self::Non è a conoscenza dell'ereditarietà e si riferisce sempre alla classe in cui viene eseguito. Se stai usando php5.3 + potresti provare static::TESTcome static::è a conoscenza dell'ereditarietà.

La differenza è che static::utilizza il "binding statico tardivo". Trova maggiori informazioni qui:

http://php.net/manual/en/language.oop5.late-static-bindings.php

Ecco un semplice script di test che ho scritto:

<?php

class One
{
    const TEST = "test1";

    function test() { echo static::TEST; }
}
class Two extends One
{
    const TEST = "test2";
}

$c = new Two();

$c->test();

produzione

test2

22
+ per aver menzionato static::.
Jason McCreary

Eccezionale. Grazie per il chiarimento e per aver fornito le informazioni aggiuntive sui binding statici tardivi (che devo ancora digerire).
Tom Auger

3
Dato che test()non è un metodo statico, perché non usarlo $this::TESTcon PHP5.3 +?
Xenos

Ciao @ Xenos - L'obiettivo dell'esempio era mostrare che il codice a livello di istanza eseguito nella classe Uno stava recuperando valori statici dalla classe Due. self :: TEST avrebbe restituito "test1" dove static :: TEST restituisce l'atteso "test2" - Spero che aiuti, grazie per la risposta!
David Farrell

Ciao @DavidFarrell - Sì, ho la self::/ static::differenza ma non capisco perché usare static::invece di $this::(non self::). C'è una differenza tra $this::e static::(poiché ce n'è una tra static::/ $this::e self::)?
Xenos

17

In PHP, self si riferisce alla classe in cui è definito il metodo o la proprietà chiamata. Quindi nel tuo caso si sta chiamando selfin ChildClass, in modo che utilizza la variabile da quella classe. Quindi si usa selfin ParentClass, quindi si riferirà alla variabile in quella classe.

se vuoi ancora che la classe figlia sovrascriva quella constdella classe genitore, regola il seguente codice nella tua classe genitore su questo:

public function showTest(){
    echo static::TEST;
    echo $this->test;
}

Nota la staticparola chiave. Questo utilizza "binding statico tardivo". Ora la tua classe genitore chiamerà la const della tua classe figlia.


pro. static :: ha fatto un lavoro in astrazione invece che in
me
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.