W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
函數(shù)類型是函數(shù)的類型。函數(shù)類型的變量可以從函數(shù)中賦值,函數(shù)類型的函數(shù)參數(shù)可以用來傳遞函數(shù)到函數(shù)調(diào)用和從函數(shù)調(diào)用返回函數(shù)。函數(shù)類型有兩種形式——內(nèi)部函數(shù)和外部函數(shù):
內(nèi)部函數(shù)只能在當(dāng)前合約內(nèi)部調(diào)用(更具體地說,在當(dāng)前代碼單元內(nèi)部,還包括內(nèi)部庫函數(shù)和繼承函數(shù)),因為它們不能在當(dāng)前合約上下文之外執(zhí)行。調(diào)用內(nèi)部函數(shù)是通過跳轉(zhuǎn)到它的入口標(biāo)簽來實現(xiàn)的,就像在內(nèi)部調(diào)用當(dāng)前合約的函數(shù)一樣。
外部函數(shù)由地址和函數(shù)簽名組成,它們可以通過外部函數(shù)調(diào)用傳遞和返回。
函數(shù)類型表示如下:
function (<parameter types>) {internal|external} [pure|view|payable] [returns (<return types>)]
與參數(shù)類型相比,返回類型不能為空——如果函數(shù)類型不應(yīng)返回任何內(nèi)容,則 必須省略整個部分。returns (<return types>)
默認(rèn)情況下,函數(shù)類型是內(nèi)部的,因此internal可以省略關(guān)鍵字。請注意,這僅適用于函數(shù)類型。必須為合約中定義的函數(shù)明確指定可見性,它們沒有默認(rèn)值。
轉(zhuǎn)換:
函數(shù)類型 A
可以隱式轉(zhuǎn)換為函數(shù)類型 B
當(dāng)且僅當(dāng): 它們的參數(shù)類型相同,返回類型相同,它們的內(nèi)部/外部屬性是相同的,并且 A
的狀態(tài)可變性比 B
的狀態(tài)可變性更具限制性,比如:
函數(shù)類型之間沒有其他轉(zhuǎn)換是可能的。
關(guān)于payableand的規(guī)則non-payable可能有點混亂,但本質(zhì)上,如果一個函數(shù)是payable,這意味著它也接受零以太幣的支付,所以它也是non-payable。另一方面,non-payable函數(shù)會拒絕發(fā)送給它的以太幣,因此non-payable函數(shù)不能轉(zhuǎn)換為payable函數(shù)。
如果未初始化函數(shù)類型變量,則調(diào)用它會導(dǎo)致Panic 錯誤。如果您在使用后調(diào)用函數(shù),也會發(fā)生同樣的情況delete 。
如果在 Solidity 的上下文之外使用外部函數(shù)類型,它們將被視為function類型,它將地址和函數(shù)標(biāo)識符一起編碼為一個bytes24類型。
請注意,當(dāng)前合約的公共功能既可以用作內(nèi)部功能,也可以用作外部功能。要f用作內(nèi)部函數(shù),只需使用f,如果要使用其外部形式,請使用this.f。
內(nèi)部類型的函數(shù)可以分配給內(nèi)部函數(shù)類型的變量,而不管它是在哪里定義的。這包括合約和庫的私有、內(nèi)部和公共功能以及免費功能。另一方面,外部函數(shù)類型僅與公共和外部合約函數(shù)兼容。庫被排除在外,因為它們需要一個delegatecall并為其選擇器使用不同的 ABI 約定。接口中聲明的函數(shù)沒有定義,因此指向它們也沒有意義。
成員:
外部(或公共)函數(shù)具有以下成員:
筆記
外部(或公共)函數(shù)曾經(jīng)有額外的成員 .gas(uint)和.value(uint). 這些在 Solidity 0.6.2 中已棄用,并在 Solidity 0.7.0 中刪除。而是使用和 分別指定發(fā)送到函數(shù)的氣體量或 wei 量。有關(guān)詳細信息,請參閱外部函數(shù)調(diào)用。{gas: ...}{value: ...}
顯示如何使用成員的示例:
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.4 <0.9.0; contract Example { function f() public payable returns (bytes4) { assert(this.f.address == address(this)); return this.f.selector; } function g() public { this.f{gas: 10, value: 800}(); } }
顯示如何使用內(nèi)部函數(shù)類型的示例:
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; library ArrayUtils { // internal functions can be used in internal library functions because // they will be part of the same code context function map(uint[] memory self, function (uint) pure returns (uint) f) internal pure returns (uint[] memory r) { r = new uint[](self.length); for (uint i = 0; i < self.length; i++) { r[i] = f(self[i]); } } function reduce( uint[] memory self, function (uint, uint) pure returns (uint) f ) internal pure returns (uint r) { r = self[0]; for (uint i = 1; i < self.length; i++) { r = f(r, self[i]); } } function range(uint length) internal pure returns (uint[] memory r) { r = new uint[](length); for (uint i = 0; i < r.length; i++) { r[i] = i; } } } contract Pyramid { using ArrayUtils for *; function pyramid(uint l) public pure returns (uint) { return ArrayUtils.range(l).map(square).reduce(sum); } function square(uint x) internal pure returns (uint) { return x * x; } function sum(uint x, uint y) internal pure returns (uint) { return x + y; } }
另一個使用外部函數(shù)類型的例子:
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract Oracle { struct Request { bytes data; function(uint) external callback; } Request[] private requests; event NewRequest(uint); function query(bytes memory data, function(uint) external callback) public { requests.push(Request(data, callback)); emit NewRequest(requests.length - 1); } function reply(uint requestID, uint response) public { // Here goes the check that the reply comes from a trusted source requests[requestID].callback(response); } } contract OracleUser { Oracle constant private ORACLE_CONST = Oracle(address(0x00000000219ab540356cBB839Cbe05303d7705Fa)); // known contract uint private exchangeRate; function buySomething() public { ORACLE_CONST.query("USD", this.oracleResponse); } function oracleResponse(uint response) public { require( msg.sender == address(ORACLE_CONST), "Only oracle can call this." ); exchangeRate = response; } }
筆記
計劃使用 Lambda 或內(nèi)聯(lián)函數(shù),但尚不支持。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: