PHP反射基础知识回顾(2)

$instance1 = Foo::getSingleton(); var_dump($instance1); $class = new ReflectionClass("Foo"); $constructor = $class->getConstructor(); if ((ReflectionProperty::IS_PUBLIC & $constructor->getModifiers()) === 0) { $constructor->setAccessible(true); } $instance2 = $class->newInstanceWithoutConstructor(); $constructor->invoke($instance2); var_dump($instance2); # 脚本执行结果 construct, instance id: 1 object(Foo)#1 (0) { } construct, instance id: 2 object(Foo)#4 (0) { }

我们成功的生成了两个实例,并调用构造函数完成对象初始化。如果没有反射API,这几乎是不可能完成的工作。

除了这三种操作,反射API几乎已无在运行时动态改变代码的行为。但作为动态语言,PHP内置了将数据转换成代码执行的能力(例如create_function/eval、动态函数名调用)。而PHP的好基友JavaScript则可以随时在运行时改变任意函数的行为:

PHP反射基础知识回顾

PHP作为最好的语言,理应能做到在运行时动态增减/改变函数定义。这就需要用到另一个PHP核心开发者“Dmitry Zenovich”打造的大杀器:runkit拓展。这部分内容不属于反射,加之本人了解不深,不再详述。

对比

整理一下反射API和函数式API在功能上的差异:

功能 函数式API 反射API
函数是否存在   function_exists   ReflectionFunction  
类是否存在   class_exits   ReflectionClass  
方法是否存在   method_exits   ReflectionMethod  
变量/属性是否存在   property_exits   ReflectionProperty  
获取类变量   get_class_vars   ReflectionClass::getProperties  
获取类方法   get_class_methods   ReflectionClass::getMethods  
获取类常量     ReflectionClass::RegetReflectionConstant(s)  
获取函数/方法参数信息     ReflectionFunction/Method::getParameters  
获取函数/方法返回值     ReflectionFunction/Method::getReturnType  
类使用的特性   class_uses   ReflectionClass::getTraits  
获取父类   class_parents   ReflectionClass::getParentClass  
获取类实现的接口   class_implements   ReflectionClass::getInterfaceNames  
获取类所在名字空间   __NAMESPACE__   ReflectionClass::getNamespaceName  
函数调用   call_user_func(_array)   ReflectionMethod(Function)::invoke(Args)  
获取类名   __CLASS__/::class   ReflectionClass::getName  
获取函数名   __METHOD__/__FUNCTION__   ReflectionFunction/Method::getName  
获取类/常量/变量/方法修饰符     ReflectionClass/Constant/Property/Method::getModifiers  
获取所在文件   __FILE__   ReflectionClass/Constant/Function/Method::getFileName  
获取所在行(范围)     ReflectionClass/Function/Method::getStartLine/getEndLine  
获取文档     ReflectionClass/Function/Method::getDocComment  
  extension_loaded   ReflectionZendExtension  
拓展   get_loaded_extensions   ReflectionExtension  
  get_extension_funcs  

从上表可以看出反射API较函数式API能提供更全面的信息。还需要注意到__FILE__这类魔术常量是编译期的工作,不是运行时的能力。

同时给出RTTI的函数式API和反射API在功能上的差异:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/f86ae5866426b6e44c2527ff21c5695b.html