摘要:轉(zhuǎn)載自我的博客在眾多的新特性中,我覺得這是最神奇甚至是詭異的一個(gè),如果有不理解這個(gè)概念的朋友,可能連它的說明都看不懂。在這個(gè)例子中操作符被重載為,操作符被重載為。再重載成操作符,以后咋跟蹤代碼。。。
轉(zhuǎn)載自我的博客:http://70.io/2014/03/php-5_6-internal-operator-overloading
在眾多php 5.6的新特性中,我覺得這是最神奇甚至是詭異的一個(gè),如果有不理解這個(gè)概念的朋友,可能連它的說明都看不懂 https://wiki.php.net/rfc/operator_overloading_gmp。
首先要說明的是,這個(gè)重載不影響到userland,也就是我們不用關(guān)心它是怎么重載的,只用關(guān)心怎么使用,它的實(shí)現(xiàn)是在php內(nèi)核代碼中。
在上面的php說明網(wǎng)址中,它舉了一個(gè)對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);
如果你會一點(diǎn)scala類似的語言,就能很好地理解了。在這個(gè)例子中+操作符被重載為gmp_add,*操作符被重載為gmp_mull。以前的基于函數(shù)式的代碼讓很多算法上的細(xì)節(jié)無法展現(xiàn)出來,改成基于操作符的就很好理解了。
它是怎么實(shí)現(xiàn)的呢?讓我們來跟蹤一下這個(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中的加號+運(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ù)還沒有轉(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來處理這次操作符運(yùn)算,如果左操作數(shù)不符合這些條件,再對右操作數(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); }
好吧,最后我來談?wù)勎业目捶ǎ晕覍@個(gè)改進(jìn)感到詭異是因?yàn)椋鼘σ话愕膚eb開發(fā)基本沒啥用,其影響基本是很少用到的數(shù)學(xué)運(yùn)算模塊。而且由于這個(gè)改進(jìn)跟userland沒啥關(guān)系,所以我們在php代碼中也用不了,別指望你能像scala那樣在class里定義操作符的實(shí)現(xiàn),這完全是兩碼事。
你只能指望這些模塊或者擴(kuò)展的作者實(shí)現(xiàn)了,而且最后實(shí)現(xiàn)也沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),本來php的函數(shù)命名就夠混亂了。。。再重載成操作符,以后咋跟蹤代碼。。。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/20695.html
摘要:類與對象基本概念如果在之后跟著的是一個(gè)包含有類名的字符串,則該類的一個(gè)實(shí)例被創(chuàng)建。如果該類屬于一個(gè)名字空間,則必須使用其完整名稱。如果一個(gè)類被聲明為,則不能被繼承。命名空間通過關(guān)鍵字來聲明。 類與對象 基本概念 new:如果在 new 之后跟著的是一個(gè)包含有類名的字符串,則該類的一個(gè)實(shí)例被創(chuàng)建。如果該類屬于一個(gè)名字空間,則必須使用其完整名稱。 Example #3 創(chuàng)建一個(gè)實(shí)例 ...
摘要:例如汽車這個(gè)名詞可以理解為汽車的總類,但這輛寶馬汽車則是一個(gè)具體的汽車對象。當(dāng)在類成員方法內(nèi)部調(diào)用的時(shí)候,可以使用偽變量調(diào)用當(dāng)前對象的屬性。在面向?qū)ο笾袆t被稱之為方法。 簡述 現(xiàn)在大伙都在講面向?qū)ο缶幊蹋俏覀円驳孟日抑粋€(gè)對象是不?不然怎么面向?qū)ο螅吭趺淳幊蹋?--- 笑話一則,但是理不虧,要搞P面向?qū)ο缶幊蹋覀兤鸫a要先搞懂對象(還有類)是什么?只有了解它,理解它,你才能駕馭它。...
摘要:然而,兩個(gè)重要的已經(jīng)獲得通過,它們將帶來一些期望已久的內(nèi)部與用戶層的一致性。綜合比較運(yùn)算符我個(gè)人最喜歡的新增特性是綜合比較運(yùn)算符,,也稱為飛船操作符。實(shí)際上,該操作符的工作方式與,或基本一致。 這是我們期待已久的 PHP 7 系列文章的第一篇。 或許你已經(jīng)知道了,我在?PHP 5.0.0 時(shí)間軸?提的 RFC (Request For Comments)通過了, PHP 7 成為 PH...
摘要:同時(shí)還支持簡寫的運(yùn)算符,表示進(jìn)行冪運(yùn)算并賦值。對應(yīng)的結(jié)構(gòu)為和。為了達(dá)到一致性將添加函數(shù)。新增函數(shù)可用來返回?cái)?shù)組中指定的一列。這種簡寫形式被稱為在起被默認(rèn)開啟,在起總是可用。三元運(yùn)算符可以簡寫省略中間的部分表達(dá)式,當(dāng)為時(shí)返回,否則返回。 PHP 5.6 1、可以使用表達(dá)式定義常量 https://php.net/manual/zh/migration56.new-features.p...
摘要:同時(shí)還支持簡寫的運(yùn)算符,表示進(jìn)行冪運(yùn)算并賦值。為了達(dá)到一致性將添加函數(shù)。新增函數(shù)可用來返回?cái)?shù)組中指定的一列。這種簡寫形式被稱為在起被默認(rèn)開啟,在起總是可用。結(jié)構(gòu)中可以用雙引號來聲明標(biāo)識符了。 PHP 5.61、可以使用表達(dá)式定義常量 https://php.net/manual/zh/mig... 在之前的 PHP 版本中,必須使用靜態(tài)值來定義常量,聲明屬性以及指定函數(shù)參數(shù)默認(rèn)值。 現(xiàn)...
閱讀 2612·2021-11-02 14:39
閱讀 4331·2021-10-11 10:58
閱讀 1458·2021-09-06 15:12
閱讀 1843·2021-09-01 10:49
閱讀 1333·2019-08-29 18:31
閱讀 1886·2019-08-29 16:10
閱讀 3342·2019-08-28 18:21
閱讀 875·2019-08-26 10:42