首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在PHP中,可以在不调用类的构造函数的情况下创建类的实例吗?

在PHP中,可以在不调用类的构造函数的情况下创建类的实例吗?
EN

Stack Overflow用户
提问于 2010-04-01 03:29:16
回答 5查看 16.5K关注 0票数 19

无论如何,有没有可能在不调用其构造函数的情况下创建php类的实例?

我有一个A类,在创建它的一个实例时传递文件,在A类的构造函数中打开这个文件。

现在在A类中,有一些函数我需要调用,但不需要传递文件,因此不需要使用打开文件的构造函数功能,因为没有传递文件。

所以我的问题是,有没有可能在不调用构造函数的情况下创建PHP类的实例?

注意:我不能使函数成为静态的,因为我正在使用函数中的一些类属性。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-04-01 03:34:21

类构造函数将始终被调用。不过,有几种方法可以解决这个问题。

第一种方法是在构造函数中为参数提供默认值,并且仅在设置了这些参数的情况下对这些参数执行特定的操作。例如:

代码语言:javascript
复制
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
    }
}

另一种选择是扩展类,这样子类的构造函数就不会调用父类的构造函数。

代码语言:javascript
复制
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
    }
}
票数 15
EN

Stack Overflow用户

发布于 2011-12-10 23:29:08

在你的情况下,我建议你考虑重新设计你的代码,这样你就不需要做这样的事情,但回答你的问题:是的,这是可能的

你可以使用PHP5.4中引入的ReflectionClass和它的方法newInstanceWithoutConstructor,这样就可以很容易地创建一个类的实例,而不用调用它的构造函数:

代码语言:javascript
复制
$reflection = new ReflectionClass("ClassName");
$instance = $reflection->newInstanceWithoutConstructor(); //That's it!
票数 32
EN

Stack Overflow用户

发布于 2010-04-01 04:04:21

注意:下面的解决方案适用于PHP5.3及更低版本。从PHP5.4开始,你还可以 .

这确实是可能的。

PHPUnit_Framework_MockObject_Generator修改

代码语言:javascript
复制
1  $myClass = unserialize(
2      sprintf(
3          'O:%d:"%s":0:{}',
4          strlen('MyClass'), 'MyClass'
5      )
6  );

请记住,在像PHPUnit这样的框架中,像这样的代码都是很好的,并且是合理的。但是,如果您必须在您的生产代码中包含这样的代码,那么您可能会做一些非常奇怪的事情。

既然你要求解释:

当你使用serialize an Object时,你会得到一个对象的字符串表示。例如

代码语言:javascript
复制
echo serialize(new StdClass) // gives O:8:"stdClass":0:{}

O的意思是对象。8是类名的字符串长度。"stdClass"显然是类名。序列化的对象设置了0属性(稍后将详细介绍),由空花括号表示。:只是分隔符。

可以使用unserialize函数将每个序列化的字符串重新创建为其原始的“活动”值。这样做,将绕过构造函数。正如查尔斯正确指出的那样,如果定义了magic method __wakeup(),就会调用它(就像序列化时调用__sleep()一样)。

在第3行,您可以看到准备与sprintf一起使用的字符串(第2行)。如您所见,类名的字符串长度为%d,类名为%s。这是为了告诉sprintf,它应该使用第4行传递给它的第一个参数作为数字,使用第二个参数作为字符串。因此,sprintf调用的结果是

代码语言:javascript
复制
'O:7:"MyClass":0:{}'

您可以将第4行中出现的两个"MyClass“替换为所需的类名,以便在不调用控制器的情况下创建要实例化的类的序列化字符串。

然后,绕过构造函数,将该字符串反序列化为第1行中的MyClass实例。未序列化的实例将拥有它的类的所有方法以及所有属性。如果MyClass中有属性,则这些属性将具有其默认值,除非您向序列化的虚拟字符串添加不同的值。

这已经够了。没什么太神奇的。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2555883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档