当前位置: 首页 > 后端技术 > PHP

通过类名动态生成对象

时间:2023-03-29 14:54:45 PHP

转载请注明文章出处:https://tlanyan.me/dynamic-ne...:使用A\B;$b=newB();//正确$str="B";$b=new$str();//错误,提示:class"B"notfound五六年前遇到过类似的问题,印象深刻。温馨提示使用“完全限定类名”的形式,可惜提问的人没看懂我说的(或者认为我的回复与问题无关):不得已,写下演示代码和@askthequestion最后让他明白:原理问题解决了,背后的原理是什么?从人的角度来看,代码的意图非常明显:动态生成B类的实例。但是从执行引擎的角度来看,就完全是另一回事了。实际上,new$classname()背后的操作行为类似于://伪代码if(class_exists($str)){$b=new$str();返回$b;}抛出ClassNotFoundException;//或者使用反射try{$reflectionClass=newReflectionClass($str);$b=$reflectionClass.newInstance();返回$b;}抛出ClassNotFoundException;根据类名动态生成实例,首先要判断这个类是否存在,对吧?PHP中相关的是class_exists函数和ReflectionClass类。上面的例子中只传入了字符串“B”,class_exists会返回true吗?答案是否定的。class_exists和ReflectionClass只会在全局类列表中按名称搜索,而不管调用函数所在(或导入)的命名空间。同理,如果使用use引入类名并做别名(as),则在class_exists中别名类也会返回false。那么PHP能否改进class_exists和ReflectionClass的行为,使其根据当前上下文进行判断呢?这个是可以做到的,但是成本非常高。原因包括:class_exists和ReflectionClass都没有表示程序上下文Context的参数;PHP有点坑:类名不会像函数、常量那样一步步向上查找;如果有多个具有相同名称类的名称,加载哪一个?如下代码所示:无论采取何种行为,都会引起投诉。保持现状,除了动态生成实例时需要完全限定类名外,没有其他槽点。而且实现简单,行为清晰一致。总结PHP作为一种脚本语言,非常灵活,但也带来了一些使用上的困惑。本文讨论的基于类名的动态生成对象将忽略当前或导入的名称空间,必须使用完全限定的类名形式。相比之下,C++不能动态生成对象。Java需要使用Class.forName的方法获取类对象,然后调用构造函数生成。Java不能直接new类名,避免了PHP中的陷阱,但是Class.forName也需要完全限定类名以避免歧义行为。参考PHPReview对PHPUsingnamespaces:fallbacktoglobalfunction/constant重载的反思