instantiator是Doctrine的一个子项目,功能是不通过构造函数来创建一个类的实例。
先不看代码,我要怎样实现这个功能呢?我只有一个类名,还不给我用new
,类也不一定有静态方法拿到实例,怎么办呢?
instantiator的答案是反序列化和反射。
反射是比较简单的,用ReflectionClass::newInstanceWithoutConstructor,但是有一点限制:内部类且为final的情况下,不能实例化。
这种情况就要通过反序列化来实例化。
例如这个类A:
class A {
public $a = 3;
}
它的一个实例序列化之后是这样的:
O:1:"A":1:{s:1:"a";i:3;}
O是序列化格式,第一个1是类名的长度,A是类名,第二个1是属性的个数,在后面是各项属性。
反序列化的时没对象属性,属性会初始化成默认值,例如O:1:"A":0:{}
也能反序列化。
那有多少种序列化格式呢?两种,O和C,C会调用Serializable接口的unserialize,O不会。
所有,我知道类名,只要构造一个字符串,然后反序列化就能得到一个实例。