PHP5.3 新特性 之 静态调用August 12, 2008

Late Static Bindings

考虑下述代码的输出

<?php
class clsParent {
    static public function say( $str ) {
        self::do_print($str);
    }

    static public function do_print( $str ) {
        echo "parent says $str";
    }
}

class clsChild extends clsParent{
    static public function do_print( $str ) {
        echo "child says $str";
    }
}

clsChild::say('Hello');
?>

你可能很希望输出 'child says Hello',但是实际上输出的是 'parent says Hello'。这是因为 self:: 指向的是类的本身,也就是 clsParent(同道理,__CLASS__ 也是一样)。

针对这一情况,PHP5.3 引入了 static:: 指向静态调用类的本身,那么很容易上述的相应函数改成

static public function say( $str ) {
    static::do_print($str);
}

就可以得到期望的结果。

__callstatic

类似 __call 这样的“魔术方法(magic methods)”,__callstatic 提供了静态调用的可能。回顾 __call 的用法

__call 方法说明了如何调用未经定义的方法。当调用未
定义方法时,方法名和方法接收的参数将会传给 __call 
方法。PHP 传递 __call 的值返回给未定义的方法。

那么,可以理解 __callstatic 是针对静态调用的方法。同样,理解下面的代码

<?php
class clsChild {
    static function a() {
        echo "i'm a";
    }

    static function __callstatic($method, $args) {
        echo 'Unknown static method' . $method . ' called with parameters:';
        echo '<pre>' . print_r($args, true) . '</pre>';
    }
}

clsChild::a();
clsChild::b();
clsChild::b('param1', 'param2');
?>

变量的静态调用

新增加的功能,使变量直接静态调用成为了可能,而不用去使用call_user_func_array 甚至 eval 等函数。考虑下面的代码

<?php
$classname  = 'clsChild';
$methodname = 'say';
$classname::$methodname();

$methodname = 'clsChild';
$param      = 'gracecode.com';
$classname::$methodname($param);
?>

进一步,变量的静态调用同时支持命名空间

<?php
// defined __autoload function.
$class = 'Project::Module::User';
$user = new $class();
$user->register($register_info);
?>

后记

PHP5.3 增强的静态调用功能,从某种意义上说,可以改变我们传统调用类甚至是编写代码的方式。

比如在传统的写法中,可以用到 __call 重载某个类,而通常的 function 通常为了调用的方便,而不是直接封装在类中。上述的调用方法能很方便得将“类似”的函数封装到某个命名空间以及类中,使代码更加的友好。

已有 4 条评论

  1. x x

    你这php写的,越来越像java了.
    尤其是 static public function say( $str ) {

  2. @x -_-! PHP 的确从 5 以后 OOP 方面有点向 Java 靠拢

  3. 脑袋不够用 oop一直让人理解不了粉晕粉晕

  4. 静态的类或方法也要继承?

Yahoo 统计