可见性和Getters(Visibility and Getters)
Solidity可以理解两种函数调用:
- “内部调用”,不创建一个真实的EVM调用,也称为“消息调用”
- “外部调用”,要创建一个真实的EVM调用,
有四种的函数和状态变量的可见性:
- 函数可以被定义为
,external
,public
或internal
,默认是private
。public
- 状态变量不能为
,默认是external
。internal
external
: 外部函数是合约接口的一部分,这意味着它们可以从其他合约调用, 也可以通过事务调用。外部函数
f
不能被内部调用,即
f()
不执行,但
this.f()
执行。外部函数在接收大数组时更有效。
public
:公共函数是合约接口的一部分,可以通过内部调用或消息调用。对公共状态变量而言,会自动生成
getter
函数。
internal
:内部的函数和状态变量只能内部访问,即当前合约或由它派生的合约,不使用关键字
this
。
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——函数修饰符