无论如何,是否可以在不调用其构造函数的情况下创建php类的实例?
我有A类,在创建它的实例时传递文件,在A类的构造函数中打开文件.
现在在A类中,有我需要调用的函数但不需要传递文件,因此不需要使用打开文件的构造函数,因为我没有传递文件.
所以我的问题是,是否可以通过任何方式创建PHP类的实例而无需调用其构造函数?
注意我不能使函数静态,因为我在函数中使用了一些类属性.
Pet*_*ler 24
在你的情况下,我建议考虑重新设计你的代码,这样你就不需要做这样的事情,但回答你的问题:是的,它是可能的.
您可以使用ReflectionClass,它的方法是在PHP 5.4中引入的newInstanceWithoutConstructor方法然后,在不调用其构造函数的情况下创建类的实例非常容易:
$reflection = new ReflectionClass("ClassName");
$instance = $reflection->newInstanceWithoutConstructor(); //That's it!
Run Code Online (Sandbox Code Playgroud)
Gor*_*don 13
注意:以下解决方案适用于PHP 5.3及更低版本.从PHP 5.4开始,您也可以通过Reflection完成此操作,如本页其他地方所示.
这确实是可能的.
修改自 PHPUnit_Framework_MockObject_Generator
1 $myClass = unserialize(
2 sprintf(
3 'O:%d:"%s":0:{}',
4 strlen('MyClass'), 'MyClass'
5 )
6 );
Run Code Online (Sandbox Code Playgroud)
请记住,这样的代码在PHPUnit这样的框架中都是好的和合理的.但是如果你的生产代码中必须有这样的代码,你可能会做一些非常奇怪的事情.
既然你要求解释:
当你序列化一个对象,你获取对象的字符串表示.例如
echo serialize(new StdClass) // gives O:8:"stdClass":0:{}
Run Code Online (Sandbox Code Playgroud)
该O
方法的对象.8
是类名的字符串长度."stdClass"
显然是班级名称.序列化对象具有0
设置的属性(稍后更多),由空花括号表示.这:
只是分隔符.
可以使用unserialize函数将每个序列化字符串重新创建为其原始"实时"值.这样做会绕过构造函数.就像Charles正确指出的那样,如果定义了魔术方法,__wakeup()
就会被调用(就像__sleep()
序列化时会被调用一样).
在第3行中,您会看到一个准备与sprintf一起使用的字符串(第2行).正如您所看到的那样%d
,类名的字符串长度为,并且类名称为%s
.这是告诉sprintf它应该使用第4行传递给它的第一个参数作为数字,第二个参数作为字符串使用.因此,sprintf调用的结果是
'O:7:"MyClass":0:{}'
Run Code Online (Sandbox Code Playgroud)
您可以将第4行中出现的"MyClass"替换为所需的类名,以创建要实例化的类的序列化字符串,而无需调用控制器.
然后,该字符串被反序列化为第1行中的MyClass实例,绕过构造函数.反序列化的实例将包含它的类的所有方法以及任何属性.如果MyClass中有属性,则这些属性将具有其默认值,除非您向序列化的虚拟字符串添加不同的值.
这已经是它了.没什么太神奇的了.
Mat*_*ins 12
始终会调用类构造函数.不过,有几种方法可以解决这个问题.
第一种方法是在构造函数中为参数提供默认值,并且只有在这些参数设置时才对这些参数执行某些操作.例如:
class MyClass {
public __construct($file = null) {
if ($file) {
// perform whatever actions need to be done when $file IS set
} else {
// perform whatever actions need to be done when $file IS NOT set
}
// perform whatever actions need to be done regardless of $file being set
}
}
Run Code Online (Sandbox Code Playgroud)
另一个选择是扩展您的类,使子类的构造函数不调用父类的构造函数.
class MyParentClass {
public __construct($file) {
// perform whatever actions need to be done regardless of $file being set
}
}
class MyChildClass extends MyParentClass {
public __construct() {
// perform whatever actions need to be done when $file IS NOT set
}
}
Run Code Online (Sandbox Code Playgroud)