Shadow33 Asked:2020-07-01 02:00:23 +0000 UTC2020-07-01 02:00:23 +0000 UTC 2020-07-01 02:00:23 +0000 UTC 递归依赖 772 class ClassA { function __construct(ClassB $paramB) { } } class ClassB { function __construct(ClassA $paramA) { } } 问题:如何解决这种依赖关系,以便执行结果只有 2 个对象而没有中间对象,或者以另一种方式使调用堆栈中只有 2 个这些构造函数。 php 1 个回答 Voted Best Answer Мелкий 2020-07-01T04:22:04Z2020-07-01T04:22:04Z 我将跳过关于为什么不可能编写那样的代码、如何处理执行此代码的架构师的讲座,然后我将立即写下你如何仍然可以逃脱。 最简单也是最坑爹的就是通过Reflection. $r = new ReflectionClass('ClassA'); $a = $r->newInstanceWithoutConstructor(); $b = new ClassB($a); $a->__construct($b); ReflectionClass::newInstanceWithoutConstructor自 PHP 5.4 起可用,并允许您在不调用构造函数的情况下获取类对象。当然,这种情况下的类可能不起作用。同时,构造函数是一个可以调用的常规类方法。 当然,当两个构造函数都需要正确初始化的参数类时,就会出现问题。遇到这种情况,直接拉出作者的手,正常重构就好了。 比较麻烦,不过也可以通过序列化机制来做。结果serialize是一个字符串。unserialize可以还原对象。您可以自己编写一个字符串,了解对象是如何序列化的。手册的评论中有一个示例(我将引用答案的完整性): function createInstanceWithoutConstructor($class){ $reflector = new ReflectionClass($class); $properties = $reflector->getProperties(); $defaults = $reflector->getDefaultProperties(); $serealized = "O:" . strlen($class) . ":\"$class\":".count($properties) .':{'; foreach ($properties as $property){ $name = $property->getName(); if($property->isProtected()){ $name = chr(0) . '*' .chr(0) .$name; } elseif($property->isPrivate()){ $name = chr(0) . $class. chr(0).$name; } $serealized .= serialize($name); if(array_key_exists($property->getName(),$defaults) ){ $serealized .= serialize($defaults[$property->getName()]); } else { $serealized .= serialize(null); } } $serealized .="}"; return unserialize($serealized); } 随着代码的更正,很可能即使在 PHP4 中也可以创建一个对象。但并非所有类都可以序列化,并相应地解包回来。
我将跳过关于为什么不可能编写那样的代码、如何处理执行此代码的架构师的讲座,然后我将立即写下你如何仍然可以逃脱。
最简单也是最坑爹的就是通过
Reflection
.ReflectionClass::newInstanceWithoutConstructor
自 PHP 5.4 起可用,并允许您在不调用构造函数的情况下获取类对象。当然,这种情况下的类可能不起作用。同时,构造函数是一个可以调用的常规类方法。当然,当两个构造函数都需要正确初始化的参数类时,就会出现问题。遇到这种情况,直接拉出作者的手,正常重构就好了。
比较麻烦,不过也可以通过序列化机制来做。结果
serialize
是一个字符串。unserialize
可以还原对象。您可以自己编写一个字符串,了解对象是如何序列化的。手册的评论中有一个示例(我将引用答案的完整性):随着代码的更正,很可能即使在 PHP4 中也可以创建一个对象。但并非所有类都可以序列化,并相应地解包回来。