深入理解Solidity——可见性和Getters

可见性和Getters(Visibility and Getters)

Solidity可以理解两种函数调用:

  • “内部调用”,不创建一个真实的EVM调用,也称为“消息调用”
  • “外部调用”,要创建一个真实的EVM调用,

有四种的函数和状态变量的可见性:

  • 函数可以被定义为external, public, internalprivate,默认是 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。

上一篇:深入理解Solidity——创建合约

下一篇:深入理解Solidity——函数修饰符

你可能感兴趣的:(Solidity文档翻译系列,以太坊去中心化应用开发)