Solidity語言學習筆記————22、可見性和Getters

FLy_鵬程萬里發表於2018-07-02

可見性和Getters(Visibility and Getters)

Solidity可以理解兩種函式呼叫:

  • “內部呼叫”,不建立一個真實的EVM呼叫,也稱為“訊息呼叫”
  • “外部呼叫”,要建立一個真實的EVM呼叫,

有四種的函式和狀態變數的可見性:

  • 函式可以被定義為externalpublicinternal 或 private,預設是 public
  • 狀態變數不能為 external,預設是 internal

external外部函式是合約介面的一部分,這意味著它們可以從其他合約呼叫, 也可以通過事務呼叫。外部函式f不能被內部呼叫,即 f()不執行,但this.f()執行。外部函式在接收大陣列時更有效。

public:公共函式是合約介面的一部分,可以通過內部呼叫或訊息呼叫。對公共狀態變數而言,會自動生成getter函式。

internal:內部的函式和狀態變數只能內部訪問,即當前合約或由它派生的合約,不使用關鍵字this 。

private:私有的函式和狀態變數只能在所在的合約中可見, 在派生的合約中不可見。

註解
合約內所有內容對於所有的外部觀察者可見。用private僅僅防止其他合約來訪問和修改該合約中資訊, 但它對blockchain之外的整個世界仍然可見。

可見性修飾符放在在狀態變數的型別之後,或引數列表和函式返回的引數列表之間。

pragma solidity ^0.4.16;

contract C {
    function f(uint a) private pure returns (uint b) { return a + 1; }
    function setData(uint a) internal { data = a; }
    uint public data;
}
在下面的示例中,D可以呼叫c.getData()來檢索狀態儲存中的資料值,但不能呼叫f.。合約E是從C派生的,因此可以呼叫compute
// 這段程式碼無法編譯

pragma solidity ^0.4.0;

contract C {
    uint private data;

    function f(uint a) private returns(uint b) { return a + 1; }
    function setData(uint a) public { data = a; }
    function getData() public returns(uint) { return data; }
    function compute(uint a, uint b) internal returns (uint) { return a+b; }
}

contract D {
    function readData() public {
        C c = new C();
        uint local = c.f(7); // error: member `f` is not visible
        c.setData(3);
        local = c.getData();
        local = c.compute(3, 5); // error: member `compute` is not visible
    }
}

contract E is C {
    function g() public {
        C c = new C();
        uint val = compute(3, 5); // access to internal member (from derived to parent contract)
    }
}

Getter函式(Getter Functions)

編譯器會自動為所有public狀態變數建立getter函式。對於下面的合約,編譯器將生成一個名為data的函式,該函式不接受任何引數,並返回uint,即狀態變數data的值。狀態變數的初始化可以在宣告中完成。

pragma solidity ^0.4.0;

contract C {
    uint public data = 42;
}

contract Caller {
    C c = new C();
    function f() public {
        uint local = c.data();
    }
}

getter函式具有外部可見性。

  • 如果在內部訪問符號(即不使用this.關鍵字),則將其作為狀態變數
  • 如果它是外部訪問的(即使用this.),則將其作為函式

下一個例子更復雜:

pragma solidity ^0.4.0;

contract Complex {
    struct Data {
        uint a;
        bytes3 b;
        mapping (uint => uint) map;
    }
    mapping (uint => mapping(bool => Data[])) public data;
}
這會生成一個如下形式的函式:
function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b) {
    a = data[arg1][arg2][arg3].a;
    b = data[arg1][arg2][arg3].b;
}

注意:struct中的mapping被省略,因為沒有好的方法來提供mapping的key。

相關文章