PHP
 Computer >> コンピューター >  >> プログラミング >> PHP

PHPの遅延静的バインディング(static::)の仕組みと使い方を解説

はじめに:遅延静的バインディングとは

PHPの遅延静的バインディング(Late Static Bindings)は、静的な継承において「実際に呼び出されたクラス」を参照できるようにする機能です。

静的メソッドを呼び出す際には、スコープ定義演算子(::)を用いてクラス名を指定します。一方、通常のインスタンスメソッドはオブジェクト名を使って呼び出します。重要なのは、static:: による参照がメソッドを定義したクラスで解決されるのではなく、実行時の情報に基づいて解決されるという点です。つまり、現在のクラスへの static 参照は、そのメソッドが属する(実際に呼び出した)クラスに対して解決されます。

self:: を使った場合の問題点

次のコードでは、親クラスが self:: を使って静的メソッドを呼び出しています。このメソッドを子クラスから呼び出しても、子クラス名は参照されません。self:: はコードを記述した時点(定義時)のクラスで解決されるためです。

<?php
class test1{
    public static $name="Raja";
    public static function name(){
        echo "name of class :" . __CLASS__;
    }
    public static function getname(){
        self::name();
    }
}
class test2 extends test1{
    public static function name(){
        echo "name of class :" . __CLASS__;
    }
}
test2::getname();
?>

出力結果

期待に反して、親クラスの名前が出力されます。

name of class :test1

static:: による遅延バインディング

self:: の代わりに static:: を使うと、実行時に遅延バインディングが行われます。

<?php
class test1{
    public static function name(){
        echo "name of class :" . __CLASS__;
    }
    public static function getname(){
        static::name();
    }
}
class test2 extends test1{
    public static function name(){
        echo "name of class :" . __CLASS__;
    }
}
test2::getname();
?>

今度は、期待どおり子クラスの名前が返されました。

出力結果

name of class :test2

非静的コンテキストでの static:: の利用

親クラスの private メソッドは子クラスにコピーされるため、そのスコープは依然として親クラスのままになります。

<?php
class test1{
    private function name(){
        echo "name of class :" . __CLASS__ ."\n";
    }
    public function getname(){
        $this->name();
        static::name();
    }
}
class test2 extends test1{
    //
}
$t2=new test2();
$t2->getname();
?>

出力結果

name of class :test1
name of class :test1

一方、親クラスのメソッドをオーバーライドすると、そのスコープは変化します。

class test3 extends test1{
    private function name() {
        /* 元のメソッドが置き換えられ、name のスコープは test3 になる */
    }
}
$t3 = new test3();
$t3->name();

出力結果

この場合、次のような致命的エラーが発生します。

PHP Fatal error: Uncaught Error: Call to private method test3::name() from context ''

まとめ

遅延静的バインディングは、継承関係にあるクラスで静的メソッドやプロパティを扱う際に欠かせない概念です。self:: は定義時のクラスに固定されるのに対し、static:: は実行時に実際に呼び出されたクラスへ解決されます。静的コンテキストでもポリモーフィズム的な振る舞いを実現したい場合は、static:: を積極的に活用するとよいでしょう。

  1. PHPのインターフェースとは?基本の使い方と特徴をサンプルコードで解説

    本記事では、PHPのオブジェクト指向プログラミングにおいて重要な設計パターンのひとつである「インターフェース」の使い方について解説します。 インターフェースを使うと、クラスが必ず実装すべき公開メソッドを宣言できます。インターフェースにはメソッド名や引数などのシグネチャのみを定義し、実際の処理内容(実装)は記述しません。インターフェースを実装するクラスは、そこで宣言されたすべてのメソッドを必ず実装しなければなりません。 インターフェースの宣言方法はクラスとよく似ていますが、宣言時には class の代わりに interface キーワードを使用し、すべてのメソッドは処理内容を持たない状態で宣言し

  2. PHPの抽象クラス(Abstract Class)とは?特徴と実装例をわかりやすく解説

    はじめにPHP5以降、本格的なオブジェクト指向モデルが導入されました。オブジェクト指向の主な概念には、クラス、オブジェクト、カプセル化、ポリモーフィズム(多態性)、抽象クラスやfinalクラス、インターフェース、継承などがあります。本記事では、その中でも「抽象クラス(Abstract Class)」に焦点を当て、PHPにおけるオブジェクト指向技術との関連や特徴を詳しく解説します。さらに、具体的なコード例を交えながら、抽象クラスの実装方法も学んでいきましょう。詳細に入る前に、まずは抽象クラスの定義方法から確認しておきましょう。抽象クラスの定義方法クラス名の先頭にabstractキーワードを付ける