Welcome to the website navigation,本站只接受合法正规的企业网站,欢迎站长们提交你的网站获得展示和流量有任何问题请联系站长,欢迎大家加入本站。

                
提交网站
  • 网站:76083
  • 待审:5
  • APP:577
  • 文章:304411
  • 会员:56004
文字内链包年1000元 文字内链包年1000元 文字内链包年1000元 AI办公网站 AI绘画工具 AIchat

名站导航为爱好php程序的朋友们提供php相关的教程知识。

在面向对象语言中,都会内置一些语言内置提供的基本功能类,比如JavaScript中的Array,Number等类, PhP程序中也有很多这种类,比如Directory,stdClass,Exception等类,同时一些标准扩展比如PDO等扩展中也会定义一些类, PhP程序中类是不允许重复定义的,所以在编写代码时不允许定义已经存在的类。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

同时PhP程序中有一些特殊的类:self,static和parent,相信读者对这self和parent都比较熟悉了,而static特殊类是PhP程序5.3才引入的。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

PhP程序中的static关键字非常多义:VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!


VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

在函数体内的修饰变量的static关键字用于定义静态局部变量。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

用于修饰类成员函数和成员变量时用于声明静态成员。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

(PhP程序5.3)在作用域解析符(::)前又表示静态延迟绑定的特殊类。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!


VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

这个关键字修饰的意义都表示"静态",在PhP程序手册中提到self, parent和static这几个关键字,但实际上除了static是关键字以外,其他两个均不是关键字, 在手册的关键字列表中也没有这两个关键字, 要验证这一点很简单:VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

<?php
var_dump(self); // ->  string(4) "self"
?>

上面的代码并没有报错,如果你把error_reporting(E_ALL)打开,就能看到实际是什么情况了: 运行这段代码会出现“ Notice: Use of undefined constant self - assumed 'self'“, 也就是说PhP程序把self当成一个普通常量了,尝试未定义的常量会把产量本身当成一个字符串, 例如上例的”self",不过同时会出一个NOTICE,这就是说self这个标示符并没有什么特殊的。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

<?php
define('self', "stdClass");
echo self; // stdClass
?>

不同语言中的关键字的意义会有些区别,Wikipedia上的解释是: 具有特殊含义的标示符或者单词,从这个意义上说$this也算是一个关键字,但在PhP程序的关键字列表中并没有。 PhP程序的关键字和C/C 一样属于保留字(关键字),关键字用于表示特定的语法形式,例如函数定义,流程控制等结构。 这些关键字有他们的特定的使用场景,而上面提到的self和parent并没有这样的限制。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

self,parent,static类

前面已经说过self的特殊性。self是一个特殊类,它指向当前类,但只有在类定义内部才有效, 但也并不一定指向类本身这个特殊类,比如前面的代码,如果放在类方法体内运行,echo self; 还是会输出常量self的值,而不是当前类,它不止要求在类的定义内部,还要求在类的上下文环境, 比如 new self()的时候,这时self就指向当前类,或者self::$static_varible, self::CONSTANT类似的作用域解析符号(::),这时的self才会作为指向本身的类而存在。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

同理parent也和self类似。下面先看看在在类的环境下的编译吧$PhP程序_SRC/Zend/zend_language_parser.y:VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

class_name_reference:
        class_name                      { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
    |   dynamic_class_name_reference    { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
;

在需要获取类名时会执行zend_do_fetch_class()函数:VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
{
    // ...
    opline->opcode = ZEND_FETCh_CLASS;
    if (class_name->op_type == IS_CONST) {
        int fetch_type;
 
        fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
        switch (fetch_type) {
            case ZEND_FETCh_CLASS_SELF:
            case ZEND_FETCh_CLASS_PARENT:
            case ZEND_FETCh_CLASS_STATIC:
                SET_UNUSED(opline->op2);
                opline->extended_value = fetch_type;
                zval_dtor(&class_name->u.constant);
                break;
            default:
                zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC);
                opline->op2 = *class_name;
                break;
        }
    } else {
        opline->op2 = *class_name;
    }
    // ...
}

上面省略了一些无关的代码,重点关注fetch_type变量。这是通过zend_get_class_fetch_type()函数获取到的。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

int zend_get_class_fetch_type(const char *class_name, uint class_name_len) /* {{{ */
{
    if ((class_name_len == sizeof("self")-1) &&
        !memcmp(class_name, "self", sizeof("self")-1)) {
        return ZEND_FETCh_CLASS_SELF;
    } else if ((class_name_len == sizeof("parent")-1) &&
        !memcmp(class_name, "parent", sizeof("parent")-1)) {
        return ZEND_FETCh_CLASS_PARENT;
    } else if ((class_name_len == sizeof("static")-1) &&
        !memcmp(class_name, "static", sizeof("static")-1)) {
        return ZEND_FETCh_CLASS_STATIC;
    } else {
        return ZEND_FETCh_CLASS_DEFAULT;
    }
}

前面的代码是Zend引擎编译类相关操作的代码,下面就到执行阶段了,self,parent等类的指向会在执行时进行获取, 找到执行opcode为ZEND_FETCh_CLASS的执行函数:VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) /* {{{ */
{
    zend_class_entry **pce;
    int use_autoload = (fetch_type & ZEND_FETCh_CLASS_NO_AUTOLOAD) == 0;
    int silent       = (fetch_type & ZEND_FETCh_CLASS_SILENT) != 0;
 
    fetch_type &= ZEND_FETCh_CLASS_MASK;
 
check_fetch_type:
    switch (fetch_type) {
        case ZEND_FETCh_CLASS_SELF:
            if (!EG(scope)) {
                zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
            }
            return EG(scope);
        case ZEND_FETCh_CLASS_PARENT:
            if (!EG(scope)) {
                zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
            }
            if (!EG(scope)->parent) {
                zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
            }
            return EG(scope)->parent;
        case ZEND_FETCh_CLASS_STATIC:
            if (!EG(called_scope)) {
                zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
            }
            return EG(called_scope);
        case ZEND_FETCh_CLASS_AUTO: {
                fetch_type = zend_get_class_fetch_type(class_name, class_name_len);
                if (fetch_type!=ZEND_FETCh_CLASS_DEFAULT) {
                    goto check_fetch_type;
                }
            }
            break;
    }
 
    if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) {
        if (use_autoload) {
            if (!silent && !EG(exception)) {
                if (fetch_type == ZEND_FETCh_CLASS_INTERFACE) {
                    zend_error(E_ERROR, "Interface '%s' not found", class_name);
                } else {
                    zend_error(E_ERROR, "Class '%s' not found", class_name);
                }
                }
            }
        }
        return NULL;
    }
    return *pce;
}

从这个函数就能看出端倪了,当需要获取self类的时候,则将EG(scope)类返回,而EG(scope)指向的正是当前类。 如果时parent类的话则从去EG(scope)->parent也就是当前类的父类,而static获取的时EG(called_scope), 分别说说EG宏的这几个字段,前面已经介绍过EG宏,它可以展开为如下这个结构体:VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

struct _zend_executor_globals {
    // ...
    zend_class_entry *scope;
    zend_class_entry *called_scope; /* Scope of the calling class */
    // ...
}
 
struct _zend_class_entry {
    char type;
    char *name;
    zend_uint name_length;
    struct _zend_class_entry *parent;
}
#define struct _zend_class_entry zend_class_entry

其中的zend_class_entry就是PhP程序中类的内部结构表示,zend_class_entry有一个parent字段,也就是该类的父类。 在EG结构体中的中called_scope会在执行过程中将当前执行的类赋值给called_scope,例如如下代码:VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

<?php
class A {
    public static funcA() {
        static::funcB();
    }
}
 
class B {
    public static funcB() {
        echo  "B::funcB()";
    }
}
 
B::funcA();
?>

代码B::funcA()执行的时候,实际执行的是B的父类A中定义的funcA函数,A::funcA()执行时当前的类(scope)指向的是类A, 而这个方法是从B类开始调用的,called_scope指向的是类B,static特殊类指向的正是called_scope,也就是当前类(触发方法调用的类), 这也是延迟绑定的原理。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!


VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

名站网址导航

PhP程序内核探索:对象VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

在之前我们很多次的说到类,对于对象来说,具有相同或相似性质的对象的抽象就是类。 因此,对象的抽象是类,类的具体化就是对象,我们常常也说对象是类的具体实例操作。 从对象的表现形式来看,它和一般的数据类型在形式上十分相似,但是它们在本质是不同的。 对象拥有方法,对象间的通信是通过方法调用,以一种消息传递的方式进行。 而我们常说的面向对象编程(OOP)使得对象具有交互能力的主要模型就是消息传递模型。 对象是消息传递的主体,它可以接收,也可以拒绝外界发来的消息。VMRAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!

好了关于php程序的知识就说到这里希望可以帮助需要的朋友。,

标签:

分享到:

  admin

注册时间:

网站:0 个   APP:3 个  文章:0 篇

  • 76083

    网站

  • 577

    APP

  • 304411

    文章

  • 56004

    会员

赶快注册账号,推广您的网站吧!
文章分类
热门网站
最新入驻APP小程序

宝贝市场2023-02-08

宝贝市场——买手和卖家商品展示

夺宝助手2023-02-08

夺宝助手小程序,查看每日快夺宝平

查诚信2023-02-08

查诚信是一款免费的商业查询工具

车价天天报2023-02-08

快速连接汽车销售,获知汽车最新报

考勤助理小程序2023-02-08

上班签到考勤,实时定位,后台轻松

汽车报价大全查询2023-02-08

汽车报价大全查询提供最新汽车市