成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP 5.6新特性之一:內(nèi)部操作符重載

canopus4u / 787人閱讀

摘要:轉(zhuǎn)載自我的博客在眾多的新特性中,我覺(jué)得這是最神奇甚至是詭異的一個(gè),如果有不理解這個(gè)概念的朋友,可能連它的說(shuō)明都看不懂。在這個(gè)例子中操作符被重載為,操作符被重載為。再重載成操作符,以后咋跟蹤代碼。。。

  

轉(zhuǎn)載自我的博客:http://70.io/2014/03/php-5_6-internal-operator-overloading

在眾多php 5.6的新特性中,我覺(jué)得這是最神奇甚至是詭異的一個(gè),如果有不理解這個(gè)概念的朋友,可能連它的說(shuō)明都看不懂 https://wiki.php.net/rfc/operator_overloading_gmp。

首先要說(shuō)明的是,這個(gè)重載不影響userland,也就是我們不用關(guān)心它是怎么重載的,只用關(guān)心怎么使用,它的實(shí)現(xiàn)是在php內(nèi)核代碼中。

在上面的php說(shuō)明網(wǎng)址中,它舉了一個(gè)對(duì)gmp_*模塊重載后的例子

// 重載前的代碼
$result = gmp_mod(
    gmp_add(
        gmp_mul($c0, gmp_mul($ms0, gmp_invert($ms0, $n0))),
        gmp_add(
            gmp_mul($c1, gmp_mul($ms1, gmp_invert($ms1, $n1))),
            gmp_mul($c2, gmp_mul($ms2, gmp_invert($ms2, $n2)))
        )
    ),
    gmp_mul($n0, gmp_mul($n1, $n2))
);

// 重載后的代碼
$result = (
    $c0 * $ms0 * gmp_invert($ms0, $n0)
  + $c1 * $ms1 * gmp_invert($ms1, $n1)
  + $c2 * $ms2 * gmp_invert($ms2, $n2)
) % ($n0 * $n1 * $n2);

如果你會(huì)一點(diǎn)scala類似的語(yǔ)言,就能很好地理解了。在這個(gè)例子中+操作符被重載為gmp_add,*操作符被重載為gmp_mull。以前的基于函數(shù)式的代碼讓很多算法上的細(xì)節(jié)無(wú)法展現(xiàn)出來(lái),改成基于操作符的就很好理解了。

它是怎么實(shí)現(xiàn)的呢?讓我們來(lái)跟蹤一下這個(gè)patch修改的源代碼,https://github.com/php/php-src/pull/342/files。最好先關(guān)注Zend/zend_operators.c這個(gè)文件的修改,基本上邏輯就很清晰了,比如ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)這個(gè)函數(shù),它處理了php中的加號(hào)+運(yùn)算(前面帶+的兩行是這個(gè)patch增加的內(nèi)容)

            default:
                if (!converted) {
 +                  ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB);
 +
                    zendi_convert_scalar_to_number(op1, op1_copy, result);
                    zendi_convert_scalar_to_number(op2, op2_copy, result);
                    converted = 1;

if(!converted)判斷了左右操作數(shù)還沒(méi)有轉(zhuǎn)換為number時(shí)候的處理,在以前是調(diào)用zendi_convert_scalar_to_number直接將其轉(zhuǎn)換為number然后再SUB,現(xiàn)在在前面加了個(gè)宏ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB),這個(gè)宏的實(shí)現(xiàn)細(xì)節(jié)是

#define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode)                                                  
    if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, do_operation)) {                       
        if (SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) {  
            return SUCCESS;                                                                       
        }                                                                                         
    } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, do_operation)) {                
        if (SUCCESS == Z_OBJ_HANDLER_P(op2, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) {  
            return SUCCESS;                                                                       
        }                                                                                         
    }

它先判斷左操作數(shù)是否為一個(gè)OBJECT,并且這個(gè)OBJECT內(nèi)部定義了運(yùn)算符操作的重載實(shí)現(xiàn),如果是那么就調(diào)用這個(gè)handler來(lái)處理這次操作符運(yùn)算,如果左操作數(shù)不符合這些條件,再對(duì)右操作數(shù)做一次這些判斷,基本上$a + $b你就可以理解為以下偽代碼

if ($a instanceof GMP && method_exists($a, "add")) {
    $a->add($b);
} else if ($b instanceof GMP && method_exists($b, "add")) {
    $b->add($a);
}

好吧,最后我來(lái)談?wù)勎业目捶ǎ晕覍?duì)這個(gè)改進(jìn)感到詭異是因?yàn)?,它?duì)一般的web開(kāi)發(fā)基本沒(méi)啥用,其影響基本是很少用到的數(shù)學(xué)運(yùn)算模塊。而且由于這個(gè)改進(jìn)跟userland沒(méi)啥關(guān)系,所以我們?cè)趐hp代碼中也用不了,別指望你能像scala那樣在class里定義操作符的實(shí)現(xiàn),這完全是兩碼事。

你只能指望這些模塊或者擴(kuò)展的作者實(shí)現(xiàn)了,而且最后實(shí)現(xiàn)也沒(méi)有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),本來(lái)php的函數(shù)命名就夠混亂了。。。再重載成操作符,以后咋跟蹤代碼。。。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/20695.html

相關(guān)文章

  • php易錯(cuò)筆記-類與對(duì)象,命名空間

    摘要:類與對(duì)象基本概念如果在之后跟著的是一個(gè)包含有類名的字符串,則該類的一個(gè)實(shí)例被創(chuàng)建。如果該類屬于一個(gè)名字空間,則必須使用其完整名稱。如果一個(gè)類被聲明為,則不能被繼承。命名空間通過(guò)關(guān)鍵字來(lái)聲明。 類與對(duì)象 基本概念 new:如果在 new 之后跟著的是一個(gè)包含有類名的字符串,則該類的一個(gè)實(shí)例被創(chuàng)建。如果該類屬于一個(gè)名字空間,則必須使用其完整名稱。 Example #3 創(chuàng)建一個(gè)實(shí)例 ...

    MartinHan 評(píng)論0 收藏0
  • PHP經(jīng)驗(yàn)總結(jié) - 聊聊面向?qū)ο?/b>

    摘要:例如汽車這個(gè)名詞可以理解為汽車的總類,但這輛寶馬汽車則是一個(gè)具體的汽車對(duì)象。當(dāng)在類成員方法內(nèi)部調(diào)用的時(shí)候,可以使用偽變量調(diào)用當(dāng)前對(duì)象的屬性。在面向?qū)ο笾袆t被稱之為方法。 簡(jiǎn)述 現(xiàn)在大伙都在講面向?qū)ο缶幊蹋俏覀円驳孟日抑粋€(gè)對(duì)象是不?不然怎么面向?qū)ο螅吭趺淳幊蹋?--- 笑話一則,但是理不虧,要搞P面向?qū)ο缶幊?,我們起碼要先搞懂對(duì)象(還有類)是什么?只有了解它,理解它,你才能駕馭它。...

    lpjustdoit 評(píng)論0 收藏0
  • PHP 7 值得期待的特性(上)

    摘要:然而,兩個(gè)重要的已經(jīng)獲得通過(guò),它們將帶來(lái)一些期望已久的內(nèi)部與用戶層的一致性。綜合比較運(yùn)算符我個(gè)人最喜歡的新增特性是綜合比較運(yùn)算符,,也稱為飛船操作符。實(shí)際上,該操作符的工作方式與,或基本一致。 這是我們期待已久的 PHP 7 系列文章的第一篇。 或許你已經(jīng)知道了,我在?PHP 5.0.0 時(shí)間軸?提的 RFC (Request For Comments)通過(guò)了, PHP 7 成為 PH...

    msup 評(píng)論0 收藏0
  • PHP 5.3、5.4、5.5、5.6 中的特性

    摘要:同時(shí)還支持簡(jiǎn)寫(xiě)的運(yùn)算符,表示進(jìn)行冪運(yùn)算并賦值。對(duì)應(yīng)的結(jié)構(gòu)為和。為了達(dá)到一致性將添加函數(shù)。新增函數(shù)可用來(lái)返回?cái)?shù)組中指定的一列。這種簡(jiǎn)寫(xiě)形式被稱為在起被默認(rèn)開(kāi)啟,在起總是可用。三元運(yùn)算符可以簡(jiǎn)寫(xiě)省略中間的部分表達(dá)式,當(dāng)為時(shí)返回,否則返回。 PHP 5.6 1、可以使用表達(dá)式定義常量 https://php.net/manual/zh/migration56.new-features.p...

    ysl_unh 評(píng)論0 收藏0
  • PHP 5.3、5.4、5.5、5.6 中的特性(7出來(lái)但是一樣有用)

    摘要:同時(shí)還支持簡(jiǎn)寫(xiě)的運(yùn)算符,表示進(jìn)行冪運(yùn)算并賦值。為了達(dá)到一致性將添加函數(shù)。新增函數(shù)可用來(lái)返回?cái)?shù)組中指定的一列。這種簡(jiǎn)寫(xiě)形式被稱為在起被默認(rèn)開(kāi)啟,在起總是可用。結(jié)構(gòu)中可以用雙引號(hào)來(lái)聲明標(biāo)識(shí)符了。 PHP 5.61、可以使用表達(dá)式定義常量 https://php.net/manual/zh/mig... 在之前的 PHP 版本中,必須使用靜態(tài)值來(lái)定義常量,聲明屬性以及指定函數(shù)參數(shù)默認(rèn)值。 現(xiàn)...

    Shihira 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<