3

我需要检查某个类是否扩展或实现了特定接口。

注意类名是一个变量字符串,即不会有这个类的任何实例。

用户应该从类列表中选择一个类,系统应该检查该类是否实现了某个接口。类列表是可变的(根据当前运行的 PHP 软件),其中一些类可以初始化,而另一些则不能。

这是我正在使用的代码:

function is_instance_of($obj,$cls){
    if(is_string($obj))$obj=new $obj();
    if(PHP_MAJOR_VERSION>4)return $obj instanceof $cls;
    if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls));
    return false;
}

var_dump(is_instance_of('MyClass','IMyInterface')); // in theory, true
var_dump(is_instance_of('Closure','IMyInterface')); // FATAL ERROR

最后一个测试显示以下错误:

可捕获的致命错误:在第 XX 行的 C:\Users\abcdefghijklmn\debug.php 中不允许实例化“闭包”

我尝试过的事情:

  • 使用$obj=new @$obj();:- 错误被隐藏,但它仍然出现故障/死亡。
  • 在违规块周围使用try{}catch(){}:-没有什么不同
  • 使用'class' instanceof 'class'(其中 $obj 是一个字符串):-false无条件返回

请注意,此方法中使用的强制类初始化......很糟糕。创建实例意味着不必要的内存消耗、速度损失和更容易出错(想象一些奇怪的类,当它在没有参数的情况下实例化时,它会继续破坏你的硬盘;))。所以,如果有任何其他方式,我很想知道它。


编辑:这是(希望)最终代码:-

/**
 * Cross-version instanceof replacement.
 * @param object $obj The instance to check.
 * @param stirng $cls The class/interface name to look for.
 * @return boolean Whether an object extends or implements a particular class
 *     or interface.
 * @link http://stackoverflow.com/questions/4365567/php-instanceof-over-strings-and-non-initializable-classes
 */
function is_instance_of($obj,$cls){
    if(is_string($obj) || PHP_MAJOR_VERSION>4){
        $rc=new ReflectionClass($obj);
        return $rc->implementsInterface($cls);
    }else{
        if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls));
        return false;
    }
}
4

2 回答 2

2

尝试改用 PHP 的ReflectionClass,例如

$rc = new ReflectionClass($obj);
return $rc->implementsInterface($cls);
于 2010-12-06T10:58:59.270 回答
0

使用反射类:

function is_instance_of($obj,$cls){
    $ref=new ReflectionClass($obj);
    return in_array($cls, array_keys($ref->getInterfaces());
}
于 2010-12-06T10:58:02.287 回答