tipos pass objetos new ejemplos clases php late-binding late-static-binding

pass - static php



¿Qué son exactamente los enlaces estáticos finales en PHP? (7)

A partir de PHP 5.3.0, PHP implementa una característica llamada enlace estático tardío que se puede utilizar para hacer referencia a la clase llamada en el contexto de la herencia estática.

La vinculación estática tardía intenta resolver esa limitación introduciendo una palabra clave que hace referencia a la clase que se llamó inicialmente en tiempo de ejecución. Se decidió no introducir una nueva palabra clave, sino usar static que ya estaba reservada.

Veamos un ejemplo:

<?php class Car { public static function run() { return static::getName(); } private static function getName() { return ''Car''; } } class Toyota extends Car { public static function getName() { return ''Toyota''; } } echo Car::run(); // Output: Car echo Toyota::run(); // Output: Toyota ?>

late static bindings funcionan almacenando la clase nombrada en la última "llamada no reenviada". En el caso de las llamadas al método estático, esta es la clase explícitamente nombrada (usualmente la que se encuentra a la izquierda del operador ::); en el caso de llamadas a métodos no estáticos, es la clase del objeto.

Una "llamada de reenvío" es una estática que es introducida por self:: , parent:: , static:: o, si sube en la jerarquía de clases, forward_static_call() .

La función get_called_class() se puede usar para recuperar una cadena con el nombre de la clase llamada y static:: introduce su alcance.

¿Qué son exactamente los enlaces estáticos finales en PHP?


Cito del libro: "PHP Master escribe código de vanguardia".

La vinculación estática tardía fue una característica introducida con php 5.3. Nos permite heredar métodos estáticos de una clase padre y hacer referencia a la clase hija a la que se llama.

Esto significa que puede tener una clase abstracta con métodos estáticos y hacer referencia a las implementaciones concretas de la clase secundaria utilizando la notación static :: method () en lugar del self :: method ().

No dude en echar un vistazo a la documentación oficial de PHP también: http://php.net/manual/en/language.oop5.late-static-bindings.php

Ejemplo:

<?php class Animal { public static function StaticCall() { // Parent object invokes its own getAnimalName() // Child object invokes its own getAnimalName() instead of parent''s getAnimalName() return static::getAnimalName(); } public static function SelfCall() { return self::getWeight(); } private static function getAnimalName(){ return ''Animal <br />''; } private static function getWeight(){ return ''10 kg <br />''; } } class Bird extends Animal { public static function getAnimalName(){ return ''Bird <br />''; } private static function getWeight(){ return ''2 kg <br />''; } } echo Animal::StaticCall(); // Animal echo Animal::SelfCall(); // 10 kg echo Bird::StaticCall(); // Bird invokes method from own object echo Bird::SelfCall(); // 10 kg invokes method from parent

En el código anterior, puede ver dos clases Animal que es la clase principal y Bird que es la clase secundaria. Tanto Animal como Bird tienen un getAnimalName() y getWeight() . La superclase Animal tiene dos métodos: StaticCall() y SelfCall() .

El método StaticCall() invoca getAnimalName() utilizando la palabra clave static .
El método SelfCall() invoca getWeight() utilizando la palabra clave self .

La pregunta que tenemos ahora es: ¿ en qué contexto se getAnimalName() ?

La respuesta: static::getAnimalName() identifica el contexto e invoca el método dentro de ese contexto.

Si invoca Bird::StaticCall() el código ejecutará StaticCall() que está en Animal . Entonces static::getAnimalName() invocará y ejecutará desde Bird el método getAnimalName() .

Esto difiere de self:: , porque self:: siempre invoca el método dentro del objeto self se define en. Así que si self::getWeight() se define en el objeto Animal en el método SelfCall() y Bird::SelfCall() sería llamado entonces self::getWeight() invoca getWeight() en el contexto del objeto Animal .


Definitivamente debe leer Enlaces estáticos tardíos en el manual de PHP. Sin embargo, trataré de darle un resumen rápido.

Básicamente, se reduce al hecho de que la palabra clave self no sigue las mismas reglas de herencia. self siempre se resuelve en la clase en la que se usa. Esto significa que si crea un método en una clase principal y lo llama desde una clase secundaria, self no hará referencia al elemento secundario como podría esperar.

La vinculación estática tardía introduce un nuevo uso para la palabra clave static , que aborda esta deficiencia particular. Cuando usa static , representa la clase en la que la usa por primera vez, es decir. se ''une'' a la clase de tiempo de ejecución.

Esos son los dos conceptos básicos detrás de esto. La forma en que operan el self , parent y static cuando static está en juego puede ser sutil, por lo que en lugar de entrar en más detalles, te recomiendo que estudies los ejemplos de la página de manual. Una vez que comprenda los conceptos básicos de cada palabra clave, los ejemplos son bastante necesarios para ver qué tipo de resultados va a obtener.


El ejemplo más simple para mostrar la diferencia.
Nota, self :: $ c

class A { static $c = 7; public static function getVal() { return self::$c; } } class B extends A { static $c = 8; } B::getVal(); // 7

Encuadernación estática tardía, nota estática :: $ c

class A { static $c = 7; public static function getVal() { return static::$c; } } class B extends A { static $c = 8; } B::getVal(); // 8


Mirándolo desde un "¿por qué debería usar esto?" perspectiva, es básicamente una forma de cambiar el contexto desde el cual se interpreta / ejecuta el método estático.

Con self , el contexto es el que originalmente definió el método. Con static , es de la que la estás llamando.


No hay un comportamiento muy obvio:

El siguiente código produce ''alphabeta''.

class alpha { function classname(){ return __CLASS__; } function selfname(){ return self::classname(); } function staticname(){ return static::classname(); } } class beta extends alpha { function classname(){ return __CLASS__; } } $beta = new beta(); echo $beta->selfname(); // Output: alpha echo $beta->staticname(); // Output: beta

Sin embargo, si eliminamos la declaración de la función classname de la clase beta, obtenemos ''alphaalpha'' como resultado.


Por ejemplo:

abstract class Builder { public static function build() { return new static; } } class Member extends Builder { public function who_am_i() { echo ''Member''; } } Member::build()->who_am_i();