天天看點

深入了解Solidity——可見性和Getters可見性和Getters(Visibility and Getters)Getter函數(Getter Functions)

可見性和Getters(Visibility and Getters)

Solidity可以了解兩種函數調用:

  • “内部調用”,不建立一個真實的EVM調用,也稱為“消息調用”
  • “外部調用”,要建立一個真實的EVM調用,

有四種的函數和狀态變量的可見性:

  • 函數可以被定義為

    external

    ,

    public

    ,

    internal

    private

    ,預設是

    public

  • 狀态變量不能為

    external

    ,預設是

    internal

external

: 外部函數是合約接口的一部分,這意味着它們可以從其他合約調用, 也可以通過事務調用。外部函數

f

不能被内部調用,即

f()

不執行,但

this.f()

執行。外部函數在接收大數組時更有效。

public

:公共函數是合約接口的一部分,可以通過内部調用或消息調用。對公共狀态變量而言,會自動生成

getter

函數。

internal

:内部的函數和狀态變量隻能内部通路,即目前合約或由它派生的合約,不使用關鍵字

this

private

:私有的函數和狀态變量隻能在所在的合約中可見, 在派生的合約中不可見。

注解
合約内所有内容對于所有的外部觀察者可見。用

private

僅僅防止其他合約來通路和修改該合約中資訊, 但它對blockchain之外的整個世界仍然可見。

可見性修飾符放在在狀态變量的類型之後,或參數清單和函數傳回的參數清單之間。

pragma solidity ^;

contract C {
    function f(uint a) private pure returns (uint b) { return a + ; }
    function setData(uint a) internal { data = a; }
    uint public data;
}
           

在下面的示例中,

D

可以調用

c.getData()

來檢索狀态存儲中的資料值,但不能調用

f

.。合約

E

是從

C

派生的,是以可以調用

compute

// 這段代碼無法編譯

pragma solidity ^;

contract C {
    uint private data;

    function f(uint a) private returns(uint b) { return a + ; }
    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(); // error: member `f` is not visible
        c.setData();
        local = c.getData();
        local = c.compute(, ); // error: member `compute` is not visible
    }
}

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

Getter函數(Getter Functions)

編譯器會自動為所有public狀态變量建立getter函數。對于下面的合約,編譯器将生成一個名為

data

的函數,該函數不接受任何參數,并傳回

uint

,即狀态變量

data

的值。狀态變量的初始化可以在聲明中完成。

pragma solidity ^;

contract C {
    uint public data = ;
}

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

getter函數具有外部可見性。

  • 如果在内部通路符号(即不使用

    this.

    關鍵字),則将其作為狀态變量。
  • 如果它是外部通路的(即使用

    this.

    ),則将其作為函數。

下一個例子更複雜:

pragma solidity ^;

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。

上一篇:深入了解Solidity——建立合約

下一篇:深入了解Solidity——函數修飾符

繼續閱讀