143

PHPの遅延静的バインディングとは正確には何ですか?

4

8 に答える 8

212

PHP マニュアルのLate Static Bindingsを読む必要があります。とはいえ、簡単にまとめてみます。

self基本的には、キーワードが同じ継承規則に従っていない という事実に要約されます。self常に、それが使用されているクラスに解決されます。これは、親クラスでメソッドを作成し、それを子クラスから呼び出すと、self期待どおりに子を参照しないことを意味します。

static遅延静的バインディングは、この特定の欠点に対処するキーワードの新しい使用法を導入します。を使用する場合static、最初に使用するクラスを表します。ランタイム クラスに「バインド」します。

これらは、その背後にある 2 つの基本的な概念です。が実行されているときselfの操作方法は微妙な場合があるため、詳しく説明するよりも、マニュアル ページの例を参照することを強くお勧めします。各キーワードの基本を理解したら、どのような結果が得られるかを確認するには、例が必要です。parentstaticstatic

于 2009-12-16T07:57:51.410 に答える
85

PHPから: Late Static Bindings - Manual :

PHP 5.3.0 の時点で、PHP は、静的継承のコンテキストで呼び出されたクラスを参照するために使用できる遅延静的バインディングと呼ばれる機能を実装しています。

遅延静的バインディングは、実行時に最初に呼び出されたクラスを参照するキーワードを導入することで、その制限を解決しようとします。...新しいキーワードを導入するのではなく、staticすでに予約されているものを使用することにしました。

例を見てみましょう:

<?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
?>

遅延静的バインディングは、最後の「非転送呼び出し」で指定されたクラスを格納することによって機能します。::静的メソッド呼び出しの場合、これは明示的に名前が付けられたクラスです (通常は演算子の左側にあります)。非静的メソッド呼び出しの場合は、オブジェクトのクラスです。「転送呼び出し」はself::parent::static::、またはクラス階層を上に行く場合は によって導入される静的なものですforward_static_call()。この関数get_called_class()を使用して、呼び出されたクラスの名前を持つ文字列を取得し、static::そのスコープを導入できます。

于 2012-12-22T07:10:34.543 に答える
27

非常に明白な動作はありません。

次のコードは「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

ただし、ベータ クラスから classname 関数の宣言を削除すると、結果として 'alphaalpha' が得られます。

于 2013-11-19T14:06:02.957 に答える
13

本から引用しています:「PHPマスターは最先端のコードを書く」。

遅延静的バインディングは、php 5.3 で導入された機能です。親クラスから静的メソッドを継承し、呼び出される子クラスを参照できます。

これは、静的メソッドを持つ抽象クラスを持つことができ 、self::method() の代わりにstatic::method()表記を使用して子クラスの具体的な実装を参照できることを意味します。

公式の php ドキュメントも参照してください: http://php.net/manual/en/language.oop5.late-static-bindings.php


Late Static Binding を説明する最も明確な方法は、実際の例を使用することです。Template メソッド パターンで使用しています。下記参照。

abstract class AbstractTemplate {
    
    public const AWESOME_LIST = [''];
    
    public function someFunction(): void {
        $awesomeList = $this->getAwesomeList();

        // OUTPUT: ['harry','henk','john'];
        var_dump($awesomeList); 
    }


    /**
     * This function gets static constants from CHILD classes
     */
    public function getAwesomeList(): array
    {
        return static::AWESOME_LIST;
    }
}

class ConcreteTemplate extends AbstractTemplate {
    
    public const AWESOME_LIST = ['harry','henk','john'];
    
    public function someFunction(): void {
        parent::someFunction();
    }
}

$concreteTemplate = new ConcreteTemplate();
$concreteTemplate->someFunction();

staticmethod のキーワードに注意してくださいgetAwesomeList。少し変更してみましょう。

public function getAwesomeList(): array
{
    return self::AWESOME_LIST;
}

var_dumpatの出力は次のようにsomeFunctionなります。

array (size=1)
  0 => string '' (length=0)

staticキーワードはシングルトン デザイン パターンで使用されます。リンクを参照してください: https://refactoring.guru/design-patterns/singleton/php/example

于 2014-06-18T12:29:29.910 に答える
11

違いを示す最も簡単な例。
注意、self::$c

class A
{
    static $c = 7;

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

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

B::getVal(); // 7

遅延静的バインディング、static::$cに注意

class A
{
    static $c = 7;

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

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

B::getVal(); // 8
于 2016-02-23T12:00:43.797 に答える
5

例えば:

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();
于 2010-09-09T06:13:22.977 に答える