在之前的文章中[1]我們介紹了Solidity語言函數(shù)的一些基本語法按声。下面來繼續(xù)介紹作為一個分布式網絡語言所特有的internal
和external
這兩種不同的函數(shù)調用方式,以及Solidity提供的對函數(shù)調用時的可見性控制語法艾君。
一旭蠕、 調用方式
Solidity封裝了兩種函數(shù)的調用方式internal
和external
黄虱。
internal
internal
調用,實現(xiàn)時轉為簡單的EVM跳轉白热,所以它能直接使用上下文環(huán)境中的數(shù)據(jù)敛助,對于引用傳遞時將會變得非常高效(不用拷貝數(shù)據(jù))。
在當前的代碼單元內屋确,如對合約內函數(shù)纳击,引入的庫函數(shù),以及父類合約中的函數(shù)直接使用即是以internal
方式的調用攻臀。我們來看個簡單的例子:
pragma solidity ^0.4.0;
contract Test {
function f(){}
//以`internal`的方式調用
function callInternally(){
f();
}
}
在上述代碼中焕数,callInternally()
以internal
的方式對f()
函數(shù)進行了調用。
external
external
調用刨啸,實現(xiàn)為合約的外部消息調用堡赔。所以在合約初始化時不能external
的方式調用自身函數(shù),因為合約還未初始化完成设联。下面來看一個以external
方式調用的例子:
pragma solidity ^0.4.0;
contract A{
function f(){}
}
contract B{
//以`external`的方式調用另一合約中的函數(shù)
function callExternal(A a){
a.f();
}
}
雖然當前合約A
和B
的代碼放在一起善已,但部署到網絡上后,它們是兩個完全獨立的合約离例,它們之間的方法調用是通過消息調用换团。上述代碼中,在合約B
中的callExternal()
以external
的方式調用了合約A
的f()
宫蛆。
external
調用時啥寇,實際是向目標合約發(fā)送一個消息調用。消息中的函數(shù)定義部分是一個24字節(jié)大小的消息體,20字節(jié)為地址辑甜,4字節(jié)為函數(shù)簽名[2]衰絮。
this
我們可以在合約的調用函數(shù)前加this.
來強制以external
方式的調用。需要注意的是這里的this
的用法與大多數(shù)語言的都不一致磷醋。
pragma solidity ^0.4.0;
contract A{
function f() internal{}
function callInternally(){
f();
}
//以`external`的方式調用
//f()只能以`internal`的方式調用
//Untitled3:7:9: Error: Member "f" not found or not visible after argument-dependent lookup in contract A
function callExternally(){
//this.f();
}
}
調用方式說明
上面所提到的internal
和external
指的函數(shù)調用方式猫牡,請不要與后面的函數(shù)可見性聲明的external
,public
邓线,internal
淌友,private
弄混。聲明只是意味著這個函數(shù)需要使用相對應的調用方式去調用骇陈。后續(xù)說明中會用以某某方式調用
震庭,來強調是對調用方式的闡述以加以區(qū)分。
二你雌、函數(shù)的可見性
Solidity為函數(shù)提供了四種可見性器联,external
,public
婿崭,internal
拨拓,private
。
external
- 聲明為
external
的可以從其它合約或通過Transaction
進行調用氓栈,所以聲明為external
的函數(shù)是合約對外接口的一部分渣磷。 - 不能以
internal
的方式進行調用。 - 有時在接收大的數(shù)據(jù)數(shù)組時性能更好授瘦。
pragma solidity ^0.4.5;
contract FuntionTest{
function externalFunc() external{}
function callFunc(){
//以`internal`的方式調用函數(shù)報錯
//Error: Undeclared identifier.
//externalFunc();
//以`external`的方式調用函數(shù)
this.externalFunc();
}
}
聲明為external
的externalFunc()
只能以external
的方式進行調用醋界,以internal
的方式調用會報Error: Undeclared identifier.
。
public
- 函數(shù)默認聲明為
public
提完。 -
public
的函數(shù)既允許以internal
的方式調用物独,也允許以external
的方式調用。 -
public
的函數(shù)由于被外部合約訪問氯葬,是合約對外接口的一部分挡篓。
pragma solidity ^0.4.5;
contract FuntionTest{
//默認是public函數(shù)
function publicFunc(){}
function callFunc(){
//以`internal`的方式調用函數(shù)
publicFunc();
//以`external`的方式調用函數(shù)
this.publicFunc();
}
}
我們可以看到聲明為public
的publicFunc()
允許兩種調用方式。
internal
- 在當前的合約或繼承的合約中帚称,只允許以
internal
的方式調用官研。
pragma solidity ^0.4.5;
contract A{
//默認是public函數(shù)
function internalFunc() internal{}
function callFunc(){
//以`internal`的方式調用函數(shù)
internalFunc();
}
}
contract B is A{
//子合約中調用
function callFunc(){
internalFunc();
}
}
上述例子中聲明為internal
的internalFunc()
在定義合約,和子合約中均只能以internal
的方式可以進行調用闯睹。
private
- 只能在當前合約中被訪問(不可在被繼承的合約中訪問)戏羽。
- 即使聲明為
private
,仍能被所有人查看到里面的數(shù)據(jù)楼吃。訪問權限只是阻止了其它合約訪問函數(shù)或修改數(shù)據(jù)始花。
pragma solidity ^0.4.5;
contract A{
//默認是public函數(shù)
function privateFunc() private{}
function callFunc(){
//以`internal`的方式調用函數(shù)
privateFunc();
}
}
contract B is A{
//不可調用`private`
function callFunc(){
//privateFunc();
}
}
上述例子中妄讯,聲明為private
的privateFunc()
只能在定義的合約中以internal
的方式進行調用。
關于作者
專注基于以太坊(Ethereum)的相關區(qū)塊鏈(Blockchain)技術酷宵,了解以太坊亥贸,Solidity,Truffle浇垦,web3.js炕置。
-
鏈接中的?函數(shù)的傳輸?shù)臄?shù)據(jù)?部分了解更多 http://me.tryblockchain.org/Solidity-call-callcode-delegatecall.html ?