天天看点

深入理解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——函数修饰符

继续阅读