A mí a primera vista también me pareció "contra-intuitivo". No necesariamente la parte que involucra constantes, sino que $this en el método de la clase base se refiera a una variable declarada en la clase base y no a la variable de la clase que hereda, cuando se está trabajando sobre una instancia de la clase heredada.
O sea, en código:
Código PHP:
class Dad {
private $className = "Dad";
public function getClassName() {
return $this->className;
}
}
class Child extends Dad {
private $className = "Child";
}
$dad = new Dad();
$child = new Child(),
echo "dad: " . $dad->getClassName() . "<br>"; // --> Dad
echo "child : " . $child ->getClassName() . "<br>"; // ---> Dad
Viendo el código, yo esperaría que $child ->getClassName() devolviera "Child", en vez de "Dad".
Decidí hacer unas pruebas con otros lenguajes -- algunos de los cuales uso habitualmente (ActionScript 2 & 3, C#), y otros que uso ocasionalmente o sólo usé alguna vez y no podría decir que los conozco a fondo, sólo lo básico para compilar una prueba (Java, C++, python).
Siempre usando el mismo código (adaptando la sintaxis, obviamente, pero respetando la estructura), el resultado me sorprendió. Excepto ActionScript 2.0 y Python, en el resto de las pruebas los resultados son iguales a los que se obtienen en PHP. Es decir, this.className en el método getClassName() de una instancia de Child se refiere a Dad::className, no a Child::className.
En síntesis, this.className se resuelve así:
ActionScript 2.0 --> Child
Python --> Child
PHP --> Dad
ActionScript 3.0 --> Dad
C# / .NET --> Dad
Java --> Dad
C++ --> Dad
Si alguien tiene una explicación "técnica" sobre el porqué de este comportamiento (que a mí particularmente me resulta "contra-intuitivo", como dije, pero que creo que es el más standard según estas pruebas), se lo agradecería. Es sólo curiosidad.
Saludos
Juan Pablo Califano