溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Solidity函數(shù)的external/internal,public/private區(qū)別是什么

發(fā)布時(shí)間:2021-12-07 15:29:26 來(lái)源:億速云 閱讀:567 作者:iii 欄目:互聯(lián)網(wǎng)科技

這篇文章主要介紹“Solidity函數(shù)的external/internal,public/private區(qū)別是什么”,在日常操作中,相信很多人在Solidity函數(shù)的external/internal,public/private區(qū)別是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Solidity函數(shù)的external/internal,public/private區(qū)別是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

1

函數(shù)類型內(nèi)部(internal)函數(shù)和外部(external)函數(shù)

函數(shù)類型是一種表示函數(shù)的類型??梢詫⒁粋€(gè)函數(shù)賦值給另一個(gè)函數(shù)類型的變量,也可以將一個(gè)函數(shù)作為參數(shù)進(jìn)行傳遞,還能在函數(shù)調(diào)用中返回函數(shù)類型變量。 函數(shù)類型有兩類:- 內(nèi)部(internal)函數(shù)和 外部(external) 函數(shù):

  • 內(nèi)部函數(shù)只能在當(dāng)前合約內(nèi)被調(diào)用(更具體來(lái)說(shuō),在當(dāng)前代碼塊內(nèi),包括內(nèi)部庫(kù)函數(shù)和繼承的函數(shù)中),因?yàn)樗鼈儾荒茉诋?dāng)前合約上下文的外部被執(zhí)行。 調(diào)用一個(gè)內(nèi)部函數(shù)是通過(guò)跳轉(zhuǎn)到它的入口標(biāo)簽來(lái)實(shí)現(xiàn)的,就像在當(dāng)前合約的內(nèi)部調(diào)用一個(gè)函數(shù)。

  • 外部函數(shù)由一個(gè)地址和一個(gè)函數(shù)簽名組成,可以通過(guò)外部函數(shù)調(diào)用傳遞或者返回。

函數(shù)類型表示成如下的形式

function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]

與參數(shù)類型相反,返回類型不能為空 —— 如果函數(shù)類型不需要返回,則需要?jiǎng)h除整個(gè) returns (<return types>) 部分。

函數(shù)類型默認(rèn)是內(nèi)部函數(shù),因此不需要聲明 internal 關(guān)鍵字。 與此相反的是,合約中的函數(shù)本身默認(rèn)是 public 的,只有當(dāng)它被當(dāng)做類型名稱時(shí),默認(rèn)才是內(nèi)部函數(shù)。

有兩種方法可以訪問(wèn)當(dāng)前合約中的函數(shù):

  • 一種是直接使用它的名字,f ;

  • 另一種是使用 this.f 。 

前者適用于內(nèi)部函數(shù),后者適用于外部函數(shù)。

如果當(dāng)函數(shù)類型的變量還沒(méi)有初始化時(shí)就調(diào)用它的話會(huì)引發(fā)一個(gè)異常。 如果在一個(gè)函數(shù)被 delete之后調(diào)用它也會(huì)發(fā)生相同的情況。

如果外部函數(shù)類型在 Solidity 的上下文環(huán)境以外的地方使用,它們會(huì)被視為 function 類型。 該類型將函數(shù)地址緊跟其函數(shù)標(biāo)識(shí)一起編碼為一個(gè) bytes24 類型。

請(qǐng)注意,當(dāng)前合約的 public 函數(shù)既可以被當(dāng)作內(nèi)部函數(shù)也可以被當(dāng)作外部函數(shù)使用。 如果想將一個(gè)函數(shù)當(dāng)作內(nèi)部函數(shù)使用,就用 f 調(diào)用,如果想將其當(dāng)作外部函數(shù),使用 this.f 。

除此之外,public(或 external)函數(shù)也有一個(gè)特殊的成員變量稱作 selector,可以返回 ABI 函數(shù)選擇器:

pragma solidity ^0.4.16;

contract Selector {  function f() public view returns (bytes4) {    return this.f.selector;
 }
}

如果使用內(nèi)部函數(shù)類型的例子:

pragma solidity ^0.4.16;

library ArrayUtils {

  // 內(nèi)部函數(shù)可以在內(nèi)部庫(kù)函數(shù)中使用,

  // 因?yàn)樗鼈儠?huì)成為同一代碼上下文的一部分

  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; 

 }

}

另外一個(gè)使用外部函數(shù)類型的例子:

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 {

    // 這里要驗(yàn)證 reply 來(lái)自可信的源

    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));

    // 使用數(shù)據(jù)

  }

}

注解 Lambda 表達(dá)式或者內(nèi)聯(lián)函數(shù)的引入在計(jì)劃內(nèi),但目前還沒(méi)支持。

2

函數(shù)可見(jiàn)性說(shuō)明符public,private,external,internal

public:內(nèi)部、外部均可見(jiàn)(參考為存儲(chǔ)/狀態(tài)變量創(chuàng)建 getter 函數(shù))

private:僅在當(dāng)前合約內(nèi)可見(jiàn)

external:僅在外部可見(jiàn)(僅可修飾函數(shù))——就是說(shuō),僅可用于消息調(diào)用(即使在合約內(nèi)調(diào)用,也只能通過(guò) this.func 的方式)

internal:僅在內(nèi)部可見(jiàn)(也就是在當(dāng)前 Solidity 源代碼文件內(nèi)均可見(jiàn),不僅限于當(dāng)前合約內(nèi),譯者注)

函數(shù)可見(jiàn)性說(shuō)明符格式:

function myFunction() <visibility specifier> returns (bool) {

    return true;
}

3

函數(shù)修改器

pure 修飾函數(shù)時(shí):不允許修改或訪問(wèn)狀態(tài)——但目前并不是強(qiáng)制的。 view 修飾函數(shù)時(shí):不允許修改狀態(tài)——但目前不是強(qiáng)制的。 payable 修飾函數(shù)時(shí):允許從調(diào)用中接收 以太幣Ether 。 constant 修飾狀態(tài)變量時(shí):不允許賦值(除初始化以外),不會(huì)占據(jù) 存儲(chǔ)插槽storage slot 。 constant 修飾函數(shù)時(shí):與 view 等價(jià)。 anonymous 修飾事件時(shí):不把事件簽名作為 topic 存儲(chǔ)。 indexed 修飾事件時(shí):將參數(shù)作為 topic 存儲(chǔ)。

到此,關(guān)于“Solidity函數(shù)的external/internal,public/private區(qū)別是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI