Pergunta

O que são exatamente as ligações estáticas final em PHP?

Foi útil?

Solução

Você definitivamente precisa ler Tarde estática Ligações no manual do PHP. No entanto, vou tentar dar-lhe um rápido resumo.

Basicamente, tudo se resume ao fato de que a palavra-chave self não seguem as mesmas regras de herança. self sempre resolve para a classe em que ela é usada. Isto significa que se você fizer um método em uma classe pai e chamá-lo de uma classe criança, self não fazem referência a criança como se poderia esperar.

estática tardia introduz obrigatório um novo uso para a palavra-chave static, que aborda esta lacuna particular. Quando você usa static, que representa a classe onde você primeiro usá-lo, ou seja. -lo 'liga' para a classe de tempo de execução.

Esses são os dois conceitos básicos por trás dele. A maneira self, parent e static operar quando static está em jogo podem ser sutis, então ao invés de ir para mais detalhes, eu recomendo fortemente que você estudar os exemplos de página manual. Depois de entender os conceitos básicos de cada palavra-chave, os exemplos são bastante necessário para ver que tipo de resultados que você vai conseguir.

Outras dicas

A partir do PHP 5.3.0, PHP implementa um recurso chamado de ligação tardia que pode ser usado para fazer referência à classe chamada no contexto de herança estática. Estática

Tarde tentativas de ligação para resolver essa limitação através da introdução de uma palavra-chave estática que referencia a classe que foi inicialmente chamado em tempo de execução. Foi decidido não introduzir uma nova palavra-chave, mas sim usar static que já foi reservado.

Vamos ver um exemplo:

<?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 trabalho armazenando a classe chamada no último "chamada não-forwarding". No caso de chamadas de métodos estáticos, esta é a classe explicitamente nomeado (geralmente o outro à esquerda do operador ::); no caso de chamadas de métodos não-estáticos, é a classe do objeto.

A "Encaminhamento de chamada" é uma estática que é introduzido por self::, parent::, static::, ou, se a subir na hierarquia de classes, forward_static_call().

A função get_called_class() pode ser usado para recuperar uma string com o nome da classe chamada e static:: introduz seu escopo.

Não é um comportamento muito óbvio:

O código a seguir produz '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

No entanto, se remover a declaração da função classname da classe beta, temos 'alphaalpha' como resultado.

Estou citando o livro: "PHP Mestre write código de ponta".

ligação tardia estática era um recurso introduzido com o PHP 5.3. Permite -nos aos métodos estáticos herdar de uma classe pai, e a referência a classe criança que está sendo chamado.

Isto significa que você pode ter uma classe abstrata com métodos estáticos e referência implementações concretas da classe filho usando o static :: method () a notação em vez do self :: método ().

Sinta-se livre para dar uma olhada na documentação oficial php, bem como: http://php.net/manual/en/language. oop5.late-static-bindings.php


A maneira mais clara para explicar atrasado vinculação estática é com um exemplo simples. Dê uma olhada nas duas definições de classe abaixo e continue a ler.

class Vehicle {
    public static function invokeDriveByStatic() {
        return static::drive(); // Late Static Binding
    }
    public static function invokeStopBySelf() {
        return self::stop(); // NOT Late Static Binding
    }
    private static function drive(){
        return "I'm driving a vehicle";
    }
    private static function stop(){
        return "I'm stopping a vehicle";
    }
}

class Car extends Vehicle  {
    protected static function drive(){
        return "I'm driving a CAR";
    }
    private static function stop(){
        return "I'm stopping a CAR";
    }
}

Vemos um Pai Class (Vehicle) e uma classe filha (de carro). O Pai Classe tem 2 métodos públicos:

  • invokeDriveByStatic
  • invokeStopBySelf

O Pai da classe também tem 2 métodos privados:

  • drive
  • stop

A classe filha substitui 2 métodos:

  • drive
  • stop

Agora vamos chamar os métodos públicos:

  • invokeDriveByStatic
  • invokeStopBySelf

Pergunte-se: Qual classe invoca invokeDriveByStatic / invokeStopBySelf? O pai ou classe Child?

Dê uma olhada abaixo:

// This is NOT Late Static Binding
// Parent class invokes from Parent. In this case Vehicle.
echo Vehicle::invokeDriveByStatic(); // I'm driving a vehicle
echo Vehicle::invokeStopBySelf(); // I'm stopping a vehicle

// This is Late Static Binding.
// Child class invokes an inherited method from Parent.
// Child class = Car, Inherited method = invokeDriveByStatic().
// ...
// The inherited method invokes a method that is overridden by the Child class.
// Overridden method = drive()
echo Car::invokeDriveByStatic(); // I'm driving a CAR

// This is NOT Late Static Binding
// Child class invokes an inherited method from Parent.
// The inherited method invokes a method inside the Vehicle context.
echo Car::invokeStopBySelf(); // I'm stopping a vehicle

A palavra-chave static é usado em um padrão de design Singleton. Ver link: https://refactoring.guru/design-patterns/singleton/php/example

O exemplo mais simples para mostrar a diferença.
Note, self :: $ c

class A
{
    static $c = 7;

    public static function getVal()
    {
        return self::$c;
    }
}

class B extends A
{
    static $c = 8;
}

B::getVal(); // 7

ligação estática tardia, nota static :: $ c

class A
{
    static $c = 7;

    public static function getVal()
    {
        return static::$c;
    }
}

class B extends A
{
    static $c = 8;
}

B::getVal(); // 8

Por exemplo:

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();

Olhando para ele a partir de um "por que eu iria usar isso?" perspectiva, é basicamente uma maneira de mudar o contexto do qual o método estático está sendo interpretada / run.

Com self, o contexto é aquele em que você definiu o método originalmente. Com static, é o que você está chamando-lo partir.

Além disso, observe se você atualizar variáveis ??estáticas em classes filhas. Achei isso (um pouco) resultado inesperado onde as atualizações criança B criança C:

class A{
    protected static $things;
}

class B extends A {
    public static function things(){
        static::$things[1] = 'Thing B';
        return static::$things; 
    }
}

class C extends A{
    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}

print_r(C::things());
// Array (
//   [2] => Thing C
// )

B::things();

print_r(C::things()); 
// Array (
//    [2] => Thing C
//    [1] => Thing B
// )

Você pode corrigi-lo, declarando a mesma variável em cada classe criança, por exemplo:

class C extends A{
    protected static $things; // add this and B will not interfere!

    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top