函數類型是一種表示函數的類型。能夠將一個函數賦值給另外一個函數類型的變量,也能夠將一個函數做爲參數進行傳遞,還能在函數調用中返回函數類型變量。 函數類型有兩類:- 內部(internal)函數和 外部(external) 函數:oracle
內部函數只能在當前合約內被調用(更具體來講,在當前代碼塊內,包括內部庫函數和繼承的函數中),由於它們不能在當前合約上下文的外部被執行。 調用一個內部函數是經過跳轉到它的入口標籤來實現的,就像在當前合約的內部調用一個函數。函數
外部函數由一個地址和一個函數簽名組成,能夠經過外部函數調用傳遞或者返回。學習
函數類型表示成以下的形式區塊鏈
function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]ui
與參數類型相反,返回類型不能爲空 —— 若是函數類型不須要返回,則須要刪除整個 returns (<return types>) 部分。this
函數類型默認是內部函數,所以不須要聲明 internal 關鍵字。 與此相反的是,合約中的函數自己默認是 public 的,只有當它被當作類型名稱時,默認纔是內部函數。編碼
有兩種方法能夠訪問當前合約中的函數:code
一種是直接使用它的名字,f ;繼承
另外一種是使用 this.f 。 事件
前者適用於內部函數,後者適用於外部函數。
若是當函數類型的變量尚未初始化時就調用它的話會引起一個異常。 若是在一個函數被 delete以後調用它也會發生相同的狀況。
若是外部函數類型在 Solidity 的上下文環境之外的地方使用,它們會被視爲 function 類型。 該類型將函數地址緊跟其函數標識一塊兒編碼爲一個 bytes24 類型。
請注意,當前合約的 public 函數既能夠被看成內部函數也能夠被看成外部函數使用。 若是想將一個函數看成內部函數使用,就用 f 調用,若是想將其看成外部函數,使用 this.f 。
除此以外,public(或 external)函數也有一個特殊的成員變量稱做 selector,能夠返回 ABI 函數選擇器:
pragma solidity ^0.4.16; contract Selector { function f() public view returns (bytes4) { return this.f.selector; } }
若是使用內部函數類型的例子:
pragma solidity ^0.4.16; library ArrayUtils { // 內部函數能夠在內部庫函數中使用, // 由於它們會成爲同一代碼上下文的一部分 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; } }
另一個使用外部函數類型的例子:
pragma solidity ^0.4.11; contract Oracle { struct Request { bytes data; function(bytes memory) external callback; } Request[] requests; event NewRequest(uint); function query(bytes data, function(bytes memory) external callback) public { requests.push(Request(data, callback)); NewRequest(requests.length - 1); } function reply(uint requestID, bytes response) public { // 這裏要驗證 reply 來自可信的源 requests[requestID].callback(response); } } contract OracleUser { Oracle constant oracle = Oracle(0x1234567); // 已知的合約 function buySomething() { oracle.query("USD", this.oracleResponse); } function oracleResponse(bytes response) public { require(msg.sender == address(oracle)); // 使用數據 } }
註解 Lambda 表達式或者內聯函數的引入在計劃內,但目前還沒支持。
public:內部、外部都可見(參考爲存儲/狀態變量建立 getter 函數)
private:僅在當前合約內可見
external:僅在外部可見(僅可修飾函數)——就是說,僅可用於消息調用(即便在合約內調用,也只能經過 this.func 的方式)
internal:僅在內部可見(也就是在當前 Solidity 源代碼文件內都可見,不只限於當前合約內,譯者注)
函數可見性說明符格式:
function myFunction() <visibility specifier> returns (bool) { return true; }
pure 修飾函數時:不容許修改或訪問狀態——但目前並非強制的。 view 修飾函數時:不容許修改狀態——但目前不是強制的。 payable 修飾函數時:容許從調用中接收 以太幣Ether 。 constant 修飾狀態變量時:不容許賦值(除初始化之外),不會佔據 存儲插槽storage slot 。 constant 修飾函數時:與 view 等價。 anonymous 修飾事件時:不把事件簽名做爲 topic 存儲。 indexed 修飾事件時:將參數做爲 topic 存儲。
本文做者:HiBlock區塊鏈社區技術佈道者輝哥
原文發佈於簡書
如下是咱們的社區介紹,歡迎各類合做、交流、學習:)