面向对象中PHP构造方法的识别

  众所周知,由于历史原因,PHP之前是使用类名作为构造函数,在PHP 5中引入的新的构造函数__construct。为了实现向后兼容性,如果PHP 5在类中找不到 __construct() 函数,它就会尝试寻找旧式的构造函数,也就是和类同名的函数。

  因此唯一会产生兼容性问题的情况是:类中已有一个名为 __construct() 的方法,但它却又不是构造函数。有如下一段代码:


  1. <?php   
  2. class Foo {    
  3.      
  4.     public function Foo() {    
  5.      
  6.     }    
  7.      
  8.     private function __construct() {    
  9.      
  10.     }    
  11. }    
  12.      
  13. new Foo();    
  14. die();   

  此时,输出为:

  Fatal error: Call to private Foo::__construct() from invalid context

  此时,PHP识别出来的构造函数是__construct,因为是private,于是在外部调用出错。好吧,我们从PHP的C源码中查找一下原因吧。从SQL的扩展类中直接查找类的定义开始:


  1. spl_iterators.c 3228行 REGISTER_SPL_STD_CLASS_EX(IteratorIterator, spl_dual_it_new, spl_funcs_IteratorIterator);    
  2. ///spl_functions.h 31行    
  3. #define REGISTER_SPL_STD_CLASS_EX(class_name, obj_ctor, funcs) \    
  4.  spl_register_std_class(&spl_ce_ ## class_name, # class_name, obj_ctor, funcs TSRMLS_CC);    
  5. //spl_functions.c 41行    
  6. PHPAPI void spl_register_std_class(zend_class_entry ** ppce, char * class_name, void * obj_ctor, const zend_function_entry * function_list TSRMLS_DC)    
  7.      
  8. //spl_functions.c 2235行    
  9. ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */    
  10. //调用do_register_internal_class函数    
  11.      
  12. //zend_API.c 2169行    
  13. static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */    
  14. //调用    
  15. zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);    
  16.      
  17. //zend_API.c 1795行    
  18. /* Look for ctor, dtor, clone    
  19. * If it's an old-style constructor, store it only if we don't have    
  20. * a constructor already.    
  21. */    
  22. if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) {    
  23.  ctor = reg_function;    
  24. } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {    
  25.  ctor = reg_function;    
  26. }     
  27.      
  28. scope->constructor = ctor; //在1961行 确认构造函数  

  以上代码为PHP 5.3.0版本

  从以上跟踪流程来看,程序在注册所有函数时,如果存在__construct(即ZEND_CONSTRUCTOR_FUNC_NAME)时,会覆盖class_name(类名)的构造函数,使其作为常规的成员函数存在。如下所示代码:


  1. <?php   
  2. class Foo {    
  3.      
  4.     public function Foo() {    
  5.         echo 'Foo';    
  6.     }    
  7.      
  8.     public function __construct() {    
  9.         echo '__construct';    
  10.     }    
  11. }    
  12.      
  13. $foo = new Foo();    
  14. $foo->Foo();  

  对于在前面的示例中的报错,我们可以在zend/zend_object_handlers.c 1057行ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)找到出处。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索php
, 面向对象
, 函数
, 兼容性
, 方法
construct
面向对象软件构造 pdf、面向对象软件构造、面向对象构造函数、js 面向对象 构造函数、面向对象构造方法,以便于您获取更多的相关知识。

时间: 2024-10-26 11:07:38

面向对象中PHP构造方法的识别的相关文章

eclipse中头文件无法识别??

问题描述 eclipse中头文件无法识别?? 解决方案 c++中头文件C++中头文件

Java语言入门教程(十三):Java语言中继承中的构造方法问题

教程(十一)中,了解了Java语言中继承的基本概念.Java中类与类的继承 ,是单继承,主要目的是复用.子类对象可以复用父类中权限允许的属性和方法 ,所以子类的构造方法和父类的构造方法之间,有一定的调用关系,本文中将进 行详细介绍. 首先,需要记住一个事实:子类的任何一个构造方法,都将先调用父类某个 构造方法.如子类Trainer中的构造方法: public Trainer() { } 虽然这个构造方法的方法体中什么代码也没有写,但是也调用了父类 Employee的构造方法,默认调用的是Empl

php面向对象中static静态属性和静态方法的调用

 这篇文章主要介绍了php面向对象中static静态属性和静态方法的调用,实例分析了static静态属性和静态方法的原理与调用技巧,需要的朋友可以参考下     本文实例讲述了php中static静态属性和静态方法的调用.分享给大家供大家参考.具体如下: 这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么样调用),需要弄明白了他们在内存中存放位置,这样就非常容易理解了.静态属性.方法(包括静态与非静态)在内存中,只有一个位置(而非静态属性,有多少实例

php面向对象中static静态属性与方法的内存位置分析

 这篇文章主要介绍了php面向对象中static静态属性与方法的内存位置,通过内存位置实例分析了static静态属性的原理与使用技巧,需要的朋友可以参考下     本文实例分析了php面向对象中static静态属性与方法的内存位置.分享给大家供大家参考.具体如下: static静态属性的内存位置-->类,而不是对象.下面做测试来证明一下 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php header("content-type:tex

php面向对象中的魔术方法中文说明

这篇文章主要介绍了php面向对象中的魔术方法中文说明,明白这些方法才好写面向对象程序,需要的朋友可以参考下 1.__construct() 实例化对象是被自动调用.当__construct和以类名为函数名的函数 同时存在时调用__construct,另一个不背调用. 类名为函数名的函数为老版的构造函数. 2.__destruct() 当删除一个对象或一个对象操作结束是被调用. 3.__call() 对象调用某个方法.若方法不存在,这调用__call 这个方法 4.__get() 读取一个对象属性

Mac中Vmware虚拟机无法识别USB Key怎么办

  很多刚刚在Mac电脑上安装了 Vmware虚拟机的用户发现,想要用USBKey这个加密锁却发现这个USB设备不见了.所以说在虚拟机下面的windows里,是不会有这个设备的,那么,Mac中Vmware虚拟机无法识别USB Key怎么办?无奈通过bootcamp启动windows系统,是可以识别出这个设备并且可以正常使用的,而且在Mac系统下的系统信息里也能看到这个设备的信息,说明设备没有问题,应该是VMWare的问题. 根据VMWare的TroubleShooting的内容,顺利解决这个问题

java中除了构造方法可以new,数组可以new,还有什么可以new呢?

问题描述 java中除了构造方法可以new,数组可以new,还有什么可以new呢? java中除了构造方法可以new,数组可以new,还有什么可以new呢? new int[ ] new student ( ) 对象可以new吗 类可以new吗 非构造方法可以new吗 解决方案 new就是用来创建对象的实例,object有默认的构造方法,new 就会调用它,当然你自己也可以写其它形式的构造函数 解决方案二: new创建一个实例.可以的

java-android面向对象中不能重用方法

问题描述 android面向对象中不能重用方法 在我的应用中我不能重用我已经在ArabicUtility类中声明的方法.我想要做的是用Arabicutility来安排一个阿拉伯语的文本.因此,我需要做的是给已经在Arabicutility类中声明的方法传递字符串并进行转换 我想这个在面向对象中是有一些困难的,所以希望能有人帮我改一下. 这个是我在Arabicutility类中加的方法 public void addTranslate(int rid, TextView txt1) { Strin

java继承中的构造方法实例解析_java

本文实例讲述了java继承中的构造方法.分享给大家供大家参考.具体如下: 继承中的构造方法: 1.子类的构造过程中必须调用其基类的构造方法. 2.子类可以在自己的构造方法中使用super(argument_list)调用基类的构造方法.   2.1.使用this(argument_list)调用本类的另外构造方法.   2.2.如果调用super,必须写在子类构造方法的第一行. 3.如果子类的构造方法中没有显示的调用基类的构造方法,则系统默认调用基类的无参数构造方法. 4.如果子类构造方法中既没