Méthode |
Utilisation |
__construct(...) |
Constructeur d'objet appelé automatiquement facultatif ( a préalablement défini une méthode cohérente avec le nom de la classe if). Les deux implémentations de __construct() et classname() existent , dans les versions instanciées Au cours du processus, , donnera la priorité à l'appel de __construct()
|
__destruct() |
Lorsque l'instance quitte la portée, ou demande la résiliation complète , entraîneront tous l'appel implicite de la méthode __destruct() de l'instance pour gérer certains travaux de nettoyage, Par exemple, fermer un fichier ou un descripteur réseau . |
__clone() |
Par défaut ,Toutes les instances sont de véritables passages par référence.Dans php5, Pour copier réellement une instance d'objet,, vous devez utiliser le clonemot-clé.Lors de l'appel du mot-clé clone sur une instance d'objet,
La méthode __clone() sera exécutée implicitement, ce qui permet à l'objet de copier certaines données de ressources internes requises. |
__toString() |
Lors de l'utilisation de texte pour représenter un objet ,Par exemple, lors de l'utilisation de l'instruction echo ou print directement sur l'objet,
La méthode __toString() sera automatiquement appelée par le moteur Si la classe implémente cette méthode magique , devrait renvoyer Une chaîne contenant une chaîne décrivant l'état actuel de l'objet . |
__get($var ) |
Si le script demande une propriété invisible d'un objet ( n'existe pas ou est invisible en raison du contrôle d'accès )quand,
__get()la méthode magique sera appelée,Le seul paramètre est le nom de la propriété demandé.implémentation Vous peut utiliser sa propre logique interne pour déterminer la valeur de retour la plus raisonnable à renvoyer . |
__set($var , $value) |
et __get() sont très similaires à ,
__set() fournit la capacité opposée , qui est utilisée pour gérer la logique d'attribution de valeurs aux propriétés invisibles des objets . Les implémentations de __set() peuvent choisir de créer implicitement ces variables dans des tables attributaires standard , et de définir des valeurs à l'aide d'autres mécanismes de stockage , Ou lancez simplement une erreur et supprimez la valeur . |
__call($ fname, $args) |
Lorsque vous appelez des méthodes non définies d'un objet, vous pouvez obtenir de superbes résultats en utilisant __call() méthode magique Le traitement de .Cette méthode accepte deux paramètres :Le nom de la méthode appelée ,Un tableau contenant les indices numériques de tous les arguments passés dans l'appel. |
__isset($nomvar) |
php5.1.0Après , l'appel d'isset($obj->prop) n'est pas seulement un chèqueprop dans 🎜>$obj, , appellera également $obj__isset()méthode, évaluation dynamique essayez d'utiliser dynamique Que ce soit les méthodes __get() et __set() peuvent lire et écrire avec succès les attributs |
__unset($varname) |
Similaire à __isset(), php 5.1 .0 introduit une simple OOPinterface pour la fonction unset() , Il peut être utilisé pour les propriétés de l'objet,Bien que cette propriété puisse ne pas exister dans la table des propriétés standard de l'objet, Mais cela pourrait avoir du sens pour l'espace de propriété dynamique de __get() et __set() , Par conséquent, __unset() est introduit pour résoudre ce problème. |
还有其他的魔术方法功能, 它们可以通过某些接口来使用, 比如ArrayAccess接口以及一些SPL接口.
在一个内部对象的实现中, 每个这样的"魔术方法"都可以和其他方法一样实现, 只要在对象的方法列表中正确的定义PHP_ME()以及PUBLIC访问修饰符即可.对于 __get(), __set(), __call(), __isset()以及__unset(), 它们要求传递参数, 你必须定义恰当的arg_info结构来指出方法需要一个或两个参数. 下面的代码片段展示了这些木梳函数的arg_info和它们对应的PHP_ME()条目:
static
ZEND_BEGIN_ARG_INFO_EX(php_sample3_one_arg, 0, 0, 1)
ZEND_END_ARG_INFO()
static
ZEND_BEGIN_ARG_INFO_EX(php_sample3_two_args, 0, 0, 2)
ZEND_END_ARG_INFO()
static function_entry php_sample3_sc_functions[] = {
PHP_ME(Sample3_SecondClass, __construct, NULL,
ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
PHP_ME(Sample3_SecondClass, __destruct, NULL,
ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
PHP_ME(Sample3_SecondClass, __clone, NULL,
ZEND_ACC_PUBLIC|ZEND_ACC_CLONE)
PHP_ME(Sample3_SecondClass, __toString, NULL,
ZEND_ACC_PUBLIC)
PHP_ME(Sample3_SecondClass, __get, php_sample3_one_arg,
ZEND_ACC_PUBLIC)
PHP_ME(Sample3_SecondClass, __set, php_sample3_two_args,
ZEND_ACC_PUBLIC)
PHP_ME(Sample3_SecondClass, __call, php_sample3_two_args,
ZEND_ACC_PUBLIC)
PHP_ME(Sample3_SecondClass, __isset, php_sample3_one_arg,
ZEND_ACC_PUBLIC)
PHP_ME(Sample3_SecondClass, __unset, php_sample3_one_arg,
ZEND_ACC_PUBLIC)
{ NULL, NULL, NULL }
};
要注意__construct, __destruct, __clone使用位域运算符增加了额外的常量. 这三个访问修饰符对于方法而言是特殊的, 它们不能被用于其他地方.
属性
php5中对象属性的访问控制与方法的可见性有所不同. 在标准属性表中定义一个公开属性时, 就像你通常期望的, 你可以使用zend_hash_add()或add_property_*()族函数.
对于受保护的和私有的属性, 则需要使用新的ZEND_API函数:
void zend_mangle_property_name(char **dest, int *dest_length,
char *class, int class_length,
char *prop, int prop_length,
int persistent)
这个函数会分配一块新的内存, 构造一个"\0classname\0propname"格式的字符串. 如果类名是特定的类名, 比如Sample3_SecondClass, 则属性的可见性为private, 只能在Sample3_SecondClass对象实例内部可见.
如果类名指定为*, 则属性的可见性是protected, 它可以被对象实例所属类的所有祖先和后辈访问. 实际上, 属性可以以下面方式增加到对象上:
void php_sample3_addprops(zval *objvar)
{
char *propname;
int propname_len;
/* public */
add_property_long(objvar, "Chapter", 11);
/* protected */
zend_mangle_property_name(&propname, &propname_len,
"*", 1, "Title", sizeof("Title")-1, 0);
add_property_string_ex(objvar, propname, propname_len,
"PHP5 Objects", 1 TSRMLS_CC);
efree(propname);
/* Private */
zend_mangle_property_name(&propname, &propname_len,
"Sample3_SecondClass",sizeof("Sample3_SecondClass")-1,
"Section", sizeof("Section")-1, 0);
add_property_string_ex(objvar, propname, propname_len,
"Properties", 1 TSRMLS_CC);
efree(propname);
}
通过_ex()版的add_property_*()族函数, 可以明确标记属性名的长度. 这是需要的, 因为在protected和private属性名中会包含NULL字节, 而strlen()认为NULL字节是字符串终止标记, 这样将导致属性名被认为是空. 要注意的是_ex()版本的add_property_*()函数还要求显式的传递TSRMLS_CC. 而通常它是通过宏扩展隐式的传递的.
定义类常量和定义类属性非常相似. 两者的关键不同点在于它们的持久性, 因为属性的生命周期是伴随的实例的, 它发生在请求中, 而常量是和类定义在一起的, 只能在MINIT阶段定义.
由于标准的zval *维护宏的函数假定了非持久性, 所以你需要手动写不少代码. 考虑下面的函数:
void php_sample3_register_constants(zend_class_entry *ce)
{
zval *constval;
/* 基本的标量值可以使用Z_*()去设置它们的值 */
constval = pemalloc(sizeof(zval), 1);
INIT_PZVAL(constval);
ZVAL_DOUBLE(constval, 2.7182818284);
zend_hash_add(&ce->constants_table, "E", sizeof("E"),
(void*)&constval, sizeof(zval*), NULL);
/* 字符串需要额外的空间分配 */
constval = pemalloc(sizeof(zval), 1);
INIT_PZVAL(constval);
Z_TYPE_P(constval) = IS_STRING;
Z_STRLEN_P(constval) = sizeof("Hello World") - 1;
Z_STRVAL_P(constval) = pemalloc(Z_STRLEN_P(constval)+1, 1);
memcpy(Z_STRVAL_P(constval), "Hello World",
Z_STRLEN_P(constval) + 1);
zend_hash_add(&ce->constants_table,
"GREETING", sizeof("GREETING"),
(void*)&constval, sizeof(zval*), NULL);
/* Objects, Arrays, and Resources can't be constants */
}
PHP_MINIT_FUNCTION(sample3)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, PHP_SAMPLE3_SC_NAME,
php_sample3_sc_functions);
php_sample3_sc_entry =
zend_register_internal_class(&ce TSRMLS_CC);
php_sample3_register_constants(php_sample3_sc_entry);
return SUCCESS;
}
在这之下, 这些类常量就可以访问了, 分别是: Sample3_SecondClass::E和Sample3_SecondClass::GREETING.
接口
接口的定义和类的定义除了几个差异外基本一致. 首先是所有的方法都定义为抽象的, 这可以通过PHP_ABSTRACT_ME()宏来完成.
static function_entry php_sample3_iface_methods[] = {
PHP_ABSTRACT_ME(Sample3_Interface, workerOne, NULL)
PHP_ABSTRACT_ME(Sample3_Interface, workerTwo, NULL)
PHP_ABSTRACT_ME(Sample3_Interface, workerThree, NULL)
{ NULL, NULL, NULL }
};
由于这些方法是抽象的, 所以不需要实现. 接下来的第二个差异就是注册. 和一个实际的类注册类似, 首先调用INIT_CLASS_ENTRY和zend_register_internal_class.
当类(zend_class_entry)可用时, 最后一部就是标记这个类是接口, 实现方法如下:
zend_class_entry *php_sample3_iface_entry;
PHP_MINIT_FUNCTION(sample3)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Sample3_Interface",
php_sample3_iface_methods);
php_sample3_iface_entry =
zend_register_internal_class(&ce TSRMLS_CC);
php_sample3_iface_entry->ce_flags|= ZEND_ACC_INTERFACE;
实现接口
假设你想让Sample3_SecondClass这个类实现Sample3_Interface这个接口, 就需要实现这个接口定义的所有抽象方法:
PHP_METHOD(Sample3_SecondClass,workerOne)
{
php_printf("Working Hard.\n");
}
PHP_METHOD(Sample3_SecondClass,workerTwo)
{
php_printf("Hardly Working.\n");
}
PHP_METHOD(Sample3_SecondClass,workerThree)
{
php_printf("Going wee-wee-wee all the way home.\n");
}
接着在php_sample3_sc_functions列表中定义它们:
PHP_ME(Sample3_SecondClass,workerOne,NULL,ZEND_ACC_PUBLIC)
PHP_ME(Sample3_SecondClass,workerTwo,NULL,ZEND_ACC_PUBLIC)
PHP_ME(Sample3_SecondClass,workerThree,NULL,ZEND_ACC_PUBLIC)
最后, 定义你新注册的类实现php_sample3_iface_entry接口:
PHP_MINIT_FUNCTION(sample3)
{
zend_class_entry ce;
/* 注册接口 */
INIT_CLASS_ENTRY(ce, "Sample3_Interface",
php_sample3_iface_methods);
php_sample3_iface_entry =
zend_register_internal_class(&ce TSRMLS_CC);
php_sample3_iface_entry->ce_flags|= ZEND_ACC_INTERFACE;
/* 注册实现接口的类 */
INIT_CLASS_ENTRY(ce, PHP_SAMPLE3_SC_NAME,
php_sample3_sc_functions);
php_sample3_sc_entry =
zend_register_internal_class(&ce TSRMLS_CC);
php_sample3_register_constants(php_sample3_sc_entry);
/* 声明实现关系 */
zend_class_implements(php_sample3_sc_entry TSRMLS_CC,
1, php_sample3_iface_entry);
return SUCCESS;
}
如果Sample3_SecondClass实现了其他接口, 比如ArrayAccess, 就需要将对应的类(zend_class_entry)作为附加参数增加到zend_class_implements()调用中, 并将现在传递为数字1的参数值相应的增大为2:
zend_class_implements(php_sample3_sc_entry TSRMLS_CC,
2, php_sample3_iface_entry, php_other_interface_entry);
句柄
ZE2并没有把所有的对象实例看做是相同的, 它为每个对象实例关联了句柄表. 当在一个对象上执行特定的操作时, 引擎调用执行对象的句柄表中自定义的行为.
标准句柄
默认情况下, 每个对象都被赋予了std_object_handlers这个内建句柄表. std_object_handlers中对应的句柄方法以及它们的行为定义如下:
当对象值的refcount增加时被调用, 比如, 当一个对象变量赋值给新的变量时. add_ref和del_ref函数的默认行为都是调整内部对象存储的refcount.
和add_ref类似, 这个方法也在修改refcount时调用, 通常是在unset()对象变量时发生的.
用于利用已有的对象实例创建一个新的实例. 默认行为是创建一个新的对象实例, 将它和原来的句柄表关联, 拷贝属性表, 如果该对象的类定义了__clone()方法, 则调用它让新的对象执行一些附加的复制工作.
zval *read_property(zval *obj, zval *prop, int type TSRMLS_DC)
void write_property(zval *obj, zval *prop, zval *value TSRMLS_DC)
在用户空间尝试以$obj->prop方式访问, 去读写对象的属性时, read_property/write_property对应的被调用. 默认的处理是首先在标准属性表中查找属性. 如果属性没有定义, 则检查是否存在__get()或__set()魔术方法, 如果有则调用该方法.
get_property_ptr_ptr() est une variante de read_property(), ce qui signifie qu'elle permet à la portée appelante de remplacer directement le zval * actuel par un nouveau. Le comportement par défaut est de renvoyer le. table de propriétés standard Adresse du pointeur de l'attribut dans .S'il n'existe pas et qu'il n'y a pas de méthode magique __get()/__set(), le pointeur est implicitement créé et renvoyé si la méthode __get() ou __set() existe. , cela entraînera l'échec de ce handle, obligeant le moteur à s'appuyer sur des appels read_property et write_property distincts
zval *read_dimension(zval *obj, zval *. idx, int tapez TSRMLS_DC)
void write_dimension(zval *obj, zval *idx, zval *value TSRMLS_DC)
read_dimension () et write_dimension() sont similaires aux read_property() et write_property() correspondants mais ils sont déclenchés lorsque l'objet est accédé sous forme de tableau à l'aide de la méthode $obj['idx'] ; . Si la classe de l'objet n'implémente pas l'interface ArrayAccess, le comportement par défaut est de déclencher une erreur ; sinon elle appelle les méthodes magiques offsetget($idx) ou offsetset($idx, $value).
Lors de la définition ou de la récupération de la valeur d'un objet, la méthode get() ou set() sera appelée sur l'objet. L'objet lui-même est passé comme. le premier paramètre. Pour set, la nouvelle valeur est passée comme deuxième paramètre ; En fait, ces méthodes sont utilisées dans les opérations arithmétiques.
Ce gestionnaire est appelé lorsque isset() est appelé sur un propriété de l'objet. Par défaut, le gestionnaire standard vérifie le nom de l'attribut spécifié par la prop. Si cet attribut n'est pas trouvé dans PHP 5.1.0 et que la méthode __isset() est définie, cette méthode sera appelée si la valeur du paramètre chk_type est 2. , alors seul l'attribut doit exister. Si la valeur de chk_type est 0, alors doit exister et ne doit pas être une valeur IS_NULL. Si la valeur de chk_type est 1, l'attribut doit exister et doit être une valeur autre que FALSE. : En PHP 5.0.x,
La signification de chk_type est cohérente avec le chk_type de has_dimension.
Lors de l'appel de isset() lors du traitement d'un objet comme d'un tableau (tel que isset($obj['idx'])), ce processeur est utilisé par défaut. vérifier si l'objet est implémenté. Si l'interface ArrayAccess est implémentée, la méthode offsetexists($idx) est appelée. Si elle n'est pas trouvée (en référence à l'appel de offsetexists()), c'est la même chose que si la méthode offsetexists() n'était pas implémentée. et 0 est renvoyé. Sinon, si chk_type est 0, renvoie directement true(1). Un chk_type de 1 indique qu'il doit appeler la méthode offsetget($idx) de l'objet et tester la valeur de retour,
Renvoie TRUE(1) uniquement si la valeur n'est pas FALSE.
void unset_property(zval *obj, zval *prop TSRMLS_DC)
void unset_dimension(zval *obj, zval *idx TSRMLS_DC)
Ces deux méthodes lorsque vous essayez de décharger les propriétés d'un objet (ou lors de l'application d'unset() à un objet dans un tableau). Le gestionnaire unset_property() supprime la propriété de la table des propriétés standard (si elle existe) ou tente d'appeler la méthode __unset($prop) implémentée (php 5.1). . 0), unset_dimension() appelle la méthode offsetunset($idx) lorsque la classe implémente ArrayAccess.
Ce gestionnaire est en fait appelé lorsque la fonction interne utilise la macro Z_OBJPROP() pour lire une propriété de la table de propriétés standard. Gestion par défaut des objets PHP. Le processeur décompresse et. renvoie Z_OBJ_P(object)->properties, qui est une véritable table de propriétés standard.
Ce gestionnaire est appelé lors de l'analyse d'une méthode objet dans la table_fonction de la classe. Si la méthode n'existe pas dans la table_fonction principale, le gestionnaire par défaut renvoie un pointeur vers l'objet _call($. name, $args) méthode enveloppée zend_function * pointer.
La fonction définie comme type ZEND_OVERLOADED_FUNCTION sera exécutée en tant que processeur call_method. Par défaut, ce processeur n'est pas défini.
Similaire au processeur get_method(), ce processeur renvoie une méthode d'objet correspondante. Référence Le constructeur dans le zend_class_entry de la classe est stocké dans. d'une manière spéciale, ce qui la rend spéciale. Le remplacement de cette méthode est très rare.
Semblable à get_constructor(), ce processeur est rarement surchargé. Son but est de mapper une instance d'objet et de revenir à sa définition de classe d'origine.
get_class_entry() est une étape de get_class_name(). Après avoir obtenu le zend_object de l'objet, il utilisera le nom de classe de l'objet ou son nom de classe parent (cela dépend de la valeur du paramètre parent ), fera une copie et retournera la copie renvoyée du nom de classe. utiliser un stockage non persistant (emalloc()).
Lorsque des opérateurs de comparaison (tels que : ==, !=, 6ccbb8b0f4c668de47d964671fff91b7, >=) sont utilisés Lorsqu'il y a deux objets, appeler compare_objects() sur le Les opérandes (les deux objets participant à la comparaison) constituent la première partie de ce travail. Sa valeur de retour est généralement 1, 0, -1, ce qui représente respectivement supérieur à, égal à et inférieur à. Par défaut, les objets sont comparés en fonction. sur leurs tables attributaires standard, en utilisant les mêmes règles de comparaison que les règles de comparaison de tableaux apprises au chapitre 8, "Travailler avec des tableaux et des tables de hachage".
Lorsque vous essayez de convertir l'objet en un autre type de données, ce processeur sera déclenché. Si Should_free est défini sur une valeur non nulle, zval_dtor() sera appelé à l'heure d'été, libérant d'abord les ressources internes. En bref, le processeur devrait essayer de représenter l'objet dans src comme dst à Out du type zval *. Ce gestionnaire n'est pas défini par défaut, mais lorsqu'il est présent, il doit renvoyer SUCCESS ou FAILURE.
Les objets qui implémentent l'accès au tableau doivent définir ce gestionnaire, qui définira le nombre actuel d'éléments dans le nombre et retournera SUCCÈS si l'instance actuelle n'implémente pas le tableau. accès, il doit renvoyer FAILURE pour que le moteur revienne en arrière et vérifie la table d'attributs standard.
Annotation : la table de poignées ci-dessus et le php-5.4.9 utilisé par le traducteur n'est plus complètement cohérent. Lors de l'étude de cette partie, les lecteurs peuvent se référer au tableau des poignées de processeur standard en bas de Zend/zend_object_handlers.c.
Méthode Magique Partie 2
使用前面看到的对象句柄表的自定义版本, 可以让内部类提供与在用户空间基于对象或类的__xxx()魔术方法相比, 相同或更多的能力.将这些自定义的句柄设置到对象实例上首先要求创建一个新的句柄表. 因为你通常不会覆写所有的句柄, 因此首先将标准句柄表拷贝到你的自定义句柄表中再去覆写你想要修改的句柄就很有意义了:
static zend_object_handlers php_sample3_obj_handlers;
int php_sample3_has_dimension(zval *obj, zval *idx,
int chk_type TSRMLS_DC)
{
/* 仅在php版本>=1.0时使用 */
if (chk_type == 0) {
/* 重新映射chk_type的值 */
chk_type = 2;
}
/* 当chk_type值为1时保持不变. 接着使用标准的hash_property方法执行逻辑 */
return php_sample3_obj_handlers.has_property(obj,
idx, chk_type TSRMLS_CC);
}
PHP_MINIT_FUNCTION(sample3)
{
zend_class_entry ce;
zend_object_handlers *h = &php_sample3_obj_handlers;
/* 注册接口 */
INIT_CLASS_ENTRY(ce, "Sample3_Interface",
php_sample3_iface_methods);
php_sample3_iface_entry =
zend_register_internal_class(&ce TSRMLS_CC);
php_sample3_iface_entry->ce_flags = ZEND_ACC_INTERFACE;
/* 注册SecondClass类 */
INIT_CLASS_ENTRY(ce, PHP_SAMPLE3_SC_NAME,
php_sample3_sc_functions);
php_sample3_sc_entry =
zend_register_internal_class(&ce TSRMLS_CC);
php_sample3_register_constants(php_sample3_sc_entry);
/* 实现AbstractClass接口 */
zend_class_implements(php_sample3_sc_entry TSRMLS_CC,
1, php_sample3_iface_entry);
/* 创建自定义句柄表 */
php_sample3_obj_handlers = *zend_get_std_object_handlers();
/* 这个句柄表的目的是让$obj['foo']的行为等价于$obj->foo */
h->read_dimension = h->read_property;
h->write_dimension = h->write_property;
h->unset_dimension = h->unset_property;
#if PHP_MAJOR_VERSION > 5 || \
(PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0)
/* php-5.1.0中, has_property和has_dimension的chk_type含义不同, 为使它们行为一致, 自己包装一个函数 */
h->has_dimension = php_sample3_has_dimension;
#else
/* php 5.0.x的has_property和has_dimension行为一致 */
h->has_dimension = h->has_property;
#endif
return SUCCESS;
}
要将这个句柄表应用到对象上, 你有两种选择. 最简单也是最具代表性的就是实现一个构造器方法, 并在其中重新赋值变量的句柄表.
PHP_METHOD(Sample3_SecondClass,__construct)
{
zval *objptr = getThis();
if (!objptr) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Constructor called statically!");
RETURN_FALSE;
}
/* 执行正常的构造器任务... */
/* 覆写句柄表 */
Z_OBJ_HT_P(objptr) = &php_sample3_obj_handlers;
}
当构造器返回时, 对象就有了新的句柄表以及对应的自定义行为. 还有一种更加受欢迎的方法是覆写类的对象创建函数.
zend_object_value php_sample3_sc_create(zend_class_entry *ce
TSRMLS_DC)
{
zend_object *object;
zend_object_value retval;
/* 返回Zend创建的对象 */
retval = zend_objects_new(&object, ce TSRMLS_CC);
/* 覆写create_object时, 属性表必须手动初始化 */
ALLOC_HASHTABLE(object->properties);
zend_hash_init(object->properties, 0, NULL,
ZVAL_PTR_DTOR, 0);
/* 覆写默认句柄表 */
retval.handlers = &php_sample3_obj_handlers;
/* 这里可能会执行其他对象初始化工作 */
return retval;
}
这样就可以在MINIT阶段注册类(zend_class_entry)之后直接将自定义句柄表附加上去.
INIT_CLASS_ENTRY(ce, PHP_SAMPLE3_SC_NAME,
php_sample3_sc_functions);
php_sample3_sc_entry =
zend_register_internal_class(&ce TSRMLS_CC);
php_sample3_sc_entry->create_object= php_sample3_sc_create;
php_sample3_register_constants(php_sample3_sc_entry);
zend_class_implements(php_sample3_sc_entry TSRMLS_CC,
1, php_sample3_iface_entry);
这两种方法唯一可预见的不同是它们发生的时机不同. 引擎在碰到new Sample3_SecondClass后会在处理构造器及它的参数之前调用create_object. 通常, 你计划覆盖的各个点使用的方法(create_object Vs. __construct)应该一致.
译注: php-5.4.9中, xxx_property/xxx_dimension这一组句柄的原型是不一致的, 因此, 按照原著中的示例, 直接将xxx_property/xxx_dimension进行映射已经不能工作, 要完成上面的功能, 需要对4个句柄均包装一个函数去映射. 由于译者没有详细跟踪具体在哪一个版本发生了这些改变, 因此这里不给出译者测试的示例(没有做兼容性处理检查), 如果读者碰到这个问题, 请检查自己所使用php版本中两组句柄原型的差异并进行相应修正.
小结
毋庸置疑, php5/ZE2的对象模型比它的前辈php4/ZE1中的对象模型更加复杂. 在看完本章中介绍的所有特性和实现细节后, 你可能已经被它的所包含的信息量搞得手足无措. 幸运的是, php中在OOP之上有一层可以让你选择你的任务所需的部分而不关心其他部分. 找到复杂性之上一个舒适的层级开始工作, 剩下的都会顺起来的.
现在已经看完了所有的php内部数据类型, 是时候回到之前的主题了: 请求生命周期. 接下来的两章, 将在你的扩展中使用线程安全全局变量增加内部状态, 定义自定义的ini设置, 定义常量, 以及向使用你扩展的用户空间脚本提供超级全局变量.
以上就是[翻译][php扩展开发和嵌入式]第11章-php5对象的内容,更多相关内容请关注PHP中文网(www.php.cn)!