对于PHPer来说,OOP是不可或缺的开发思维,但是你对php类和对象的底层实现又了解多少呢?本着知其然且知其所以然的思想,让我们一起来寻找答案~

类的底层实现可看作是之前我们讲过的变量、函数等的知识集合。所以想要理解更深入的同学最好查看下我之前的关于介绍变量、函数的文章

类的数据结构

不管是普通类还是抽象类或是接口,都存放到统一的结构体中,并且在生成中间代码时,会将此类添加到全局类列表中。当然,也是在此时,会通过类名判断该类是否已经存在,如果存在,则添加失败struct _zend_class_entry {

char type; // 和函数一样,类被拆分为两种类型:ZEND_INTERNAL_CLASS 内部类型和ZEND_USER_CLASS 用户自定义类型

char *name;// 类名称

zend_uint name_length; // 即sizeof(name) - 1

struct _zend_class_entry *parent; // 继承的父类

int refcount; // 引用数

zend_bool constants_updated;

zend_uint ce_flags;//类的类型,在编译阶段被区分是普通类,接口,抽象类

HashTable function_table; // 静态类方法和普通类方法存放集合

HashTable default_properties; // 默认属性存放集合

HashTable properties_info; // 属性信息存放集合

HashTable default_static_members;// 类本身所具有的静态变量存放集合

HashTable *static_members; // type == ZEND_USER_CLASS时,取&default_static_members;

// type == ZEND_INTERAL_CLASS时,设为NULL

HashTable constants_table; // 常量存放集合

struct _zend_function_entry *builtin_functions;// 方法定义入口

/* 魔术方法 */

//所有魔术方法单独存放,初始化时被设置为null

union _zend_function *constructor;

union _zend_function *destructor;

union _zend_function *clone;

union _zend_function *__get;

union _zend_function *__set;

union _zend_function *__unset;

union _zend_function *__isset;

union _zend_function *__call;

union _zend_function *__tostring;

union _zend_function *serialize_func;

union _zend_function *unserialize_func;

zend_class_iterator_funcs iterator_funcs;// 迭代

/* 类句柄 */

zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);

zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object,

intby_ref TSRMLS_DC);

/* 类声明的接口 */

int(*interface_gets_implemented)(zend_class_entry *iface,

zend_class_entry *class_type TSRMLS_DC);

/* 序列化回调函数指针 */

int(*serialize)(zval *object, unsignedchar**buffer, zend_uint *buf_len,

zend_serialize_data *data TSRMLS_DC);

int(*unserialize)(zval **object, zend_class_entry *ce, constunsignedchar*buf,

zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);

zend_class_entry **interfaces; // 类实现的接口

zend_uint num_interfaces; // 类实现的接口数

char *filename; // 类的存放文件地址 绝对地址

zend_uint line_start; // 类定义的开始行

zend_uint line_end; // 类定义的结束行

char *doc_comment;

zend_uint doc_comment_len;

struct _zend_module_entry *module; // 类所在的模块入口:EG(current_module)

};

由上面代码可以看出,类的成员变量、成员方法都是存放在各自的结构体中,而结构体的数据结构和之前讲解的变量和函数的数据结构一模一样,只不过编译后的成员变量和成员方法是存放在类结构体中而已

对象的生成

我们都知道,对象是new出来的,但是从底层来看,对象生成分为3步

第一步:根据类名去全局类列表内查找该类是否存在,如果存在,则获取存储类的变量

第二步:判断类是否是普通类(非抽象类或接口);如果是普通类则给需要创建的对象存放的zval容器分配内存,并设置容器类型为IS_OBJECT

第三步:执行对象初始化操作,将对象添加到全局对象列表(对象池)中

附上对象的数据结构:typedef struct _zend_object {

zend_class_entry *ce; //对象的类结构

HashTable *properties; //对象属性

HashTable *guards; /* protects from __get/__set ... recursion */

} zend_object;

获取和设置成员变量

获取成员变量:

第一步,获取对象的属性,从对象的properties查找是否存在与名称对应的属性,如果存在返回结果,如果不存在,转第二步

第二步,如果存在get魔术方法,则调用此方法获取变量,如果不存在,则报错

设置成员变量:

第一步,获取对象的属性,从对象的properties查找是否存在与名称对应的属性,如果存在且已有的值和需要设置的值相同,则不执行任何操作,否则执行变量赋值操作,如果不存在,转第二步

第二步,如果存在_set魔术方法,则调用此方法设置变量,如果不存在,转第三步

第三步,如果成员变量一直没有被设置过,则直接将此变量添加到对象的properties字段所在HashTable中。

总结

到今天为止,我们差不多已经将关于php的底层原理讲了一个遍了。当然,在这期间,不少同学跟我说,现在都已经逐渐开始使用php7了,你现在讲解的内容还是php5,会不会过时了?其实我讲解php5也是为讲php7作准备,php7毕竟是php5的延展,了解了php5之后,再去了解php7会更加容易些。而且php也是从php5开始才逐渐完善起来的,我们有必要了解下php5的内容。不过从下周开始,我们会开始从底层比较php7和php5的不同,敬请期待~

更多PHP相关技术文章,请访问PHP教程栏目进行学习!

php对象底层结构,PHP 底层原理之类和对象相关推荐

  1. 高性能分布式缓存Redis--- Redis底层结构和缓存原理 --- 持续更新

    高性能分布式缓存Redis全系列文章主目录(进不去说明还没写完)https://blog.csdn.net/grd_java/article/details/124192973 本文只是整个系列笔记的 ...

  2. python学习Day14 带参装饰器、可迭代对象、迭代器对象、for 迭代器工作原理、枚举对象、生成器及生成表达式...

    复习 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.返回内部函数对象---->  延迟执行, 开放封闭原则: 功能可以拓展,但源代 ...

  3. R语言常用基础函数:length函数查看数据对象的长度、str函数查看数据对象的结构、class函数查看数据对象的类型、names函数查看数据对象的名称

    R语言常用基础函数:length函数查看数据对象的长度.str函数查看数据对象的结构.class函数查看数据对象的类型.names函数查看数据对象的名称 目录

  4. mysql索引数据结构图解_MySQL索引底层结构与实现原理

    为什么要使用索引 MySQL官方定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构,类似于书的目录结构一样. 如果向mysql发出一条sql语句请求,查询的字段没有创建索引的话,可能 ...

  5. iOS 进阶之底层原理一OC对象原理alloc做了什么

    人狠话不多,直接上干货.这是第一篇,之后还会持续更新,当作自己学习的笔记,也同时分享给大家,希望帮助更多人. 首先,我们来思考,下面这段代码的输出是否相同.答案很明显,p1.p2.p3是指向相同的对象 ...

  6. 阿里P8架构师谈:深入探讨HashMap的底层结构、原理、扩容机制

    摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型. 随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化, ...

  7. set列表对象去重_Redis中hash、set、zset有多牛?从底层告诉你数据结构原理

    前言 今天来说下Redis中hash.set.zset的底层数据结构原理! Redis-哈希对象(hash) hash的底层存储有两种数据结构,一种是ziplist,另外一种是hashtable,这两 ...

  8. iOS底层原理总结 - OC对象的本质

    苹果官方文档 The Objective-C language defers as many decisions as it can from compile time and link time t ...

  9. HashMap的底层存储结构和实现原理

    文章目录 前言 一.HashMap是什么? 二. 数组 三. 链表 四.哈希算法 五.哈希冲突 总结 前言 HashMap实现了Map接口,我们常用来put/get操作读存键值对数据,比较典型的key ...

最新文章

  1. Redis中五大数据结构的底层实现
  2. python使用fpdf2包和pdfrw包在已有的PDF页面上添加新的页
  3. HTML怎么编写可关闭广告,JS实现关闭小广告特效
  4. IdentityServer4-EF动态配置Client和对Claims授权(二)
  5. Python合并多个Excel数据
  6. java k线绘制,用Java绘制K线图[Java编程]
  7. word公式插件_再也不用担心我的公式写不出来了:一款公式输入神器实测
  8. 每日算法系列【LeetCode 810】黑板异或游戏
  9. 【2030】排队打水问题
  10. Windows设置程序开机自启动的几种方法(整理发布)
  11. vue中处理文本不换行问题
  12. Vue面试中,经常会被问到的面试题
  13. Android 字体引入
  14. php学习日志(5)-解决Windows Live Writer错误:WindowsLive.Writer.CoreServices.HttpRequestHelper的类型初始值设定发生异常...
  15. Java实现 蓝桥杯油漆问题
  16. Visitor----------模式
  17. styled-components 基本用法
  18. 学习全栈在线教育实战项目(尚硅谷) 第一天
  19. UI----Android开发艺术字体设置
  20. git 提交部分修改代码(非全部代码)

热门文章

  1. 浅谈ROS操作系统及其应用趋势
  2. VIO-slam 系统构建
  3. linux在双系统中消失了,双系统重新安装windows后,ubuntu选项消失
  4. as5300g2 nas软件功能_【浪潮混闪存储AS5300G5-可同时提供SAN和NAS两种服务的中端混闪存储系统】价格_厂家 - 中国供应商...
  5. pythonweb开发面试_Python web 面试题(一)
  6. uni-app 手指左右滑动实现翻页效果
  7. Qt实现延时sleep函数功能
  8. HDU 3948 不同回文子串个数
  9. JavaScript——以简单的方式理解闭包
  10. [转帖]好技术领导,差技术领导