对于所有public
的状态变量,Solidity语言编译器,提供了自动为状态变量生成对应的getter(访问器)
的特性1。语言暂不提供setter
,因为不能很好控制访问权限的改值函数,不一定实用。
状态变量所创建的访问器函数,与变量同名。以interal
访问时,按状态变量的方式使用,若以external
的方式访问时,则要通过访问器函数,下面来看一个的例子:
pragma solidity ^0.4.0;
contract AccessGetter{
uint public data = 10;
function f() returns (uint, uint){
//分别以internal,external的方式访问
return (data, this.data());
}
}
上面的例子中,编译器会为我们自动生成的data()
函数。在合约内,我们可以直接操作及访问data
状态变量,但在合约外我们只能用data()
的方式来访问。另外,在合约内,我们不能直接访问data()
,因为访问器函数的可见性是external
2。
枚举
枚举的访问器与基本类型类似,均是生成与状态变量同名的函数。
pragma solidity ^0.4.0;
contract EnumGetter{
enum Color{Blue, Green, Yellow}
Color public color = Color.Green;
function f() returns (Color, Color){
return (color, this.color());
}
}
数组
前面的访问器函数,是一个与状态变量同名的无参函数。访问器一定是没有参数的么,其实不然。对于数组,我们必须提供序号来使用访问器,下面来看一个数组的访问器实例:
pragma solidity ^0.4.0;
contract ArrayGetter{
uint[] public arr = new uint[](1);
function f() returns (uint, uint){
//直接访问与以带序号参数访问器的方式访问
return (arr[0], this.arr(0));
}
}
上面的实例中,我们可以发现,对于数组访问器的使用,需要增加序号值作为参数。如果不传序号值,会报错Wrong argument count for function call: 0 arguments given but expected 1
。
映射
对于映射类型,它的访问器也是有参数的,参数为映射定义的键类型。下面来看一个映射的访问器例子。
pragma solidity ^0.4.0;
contract MappingGetter{
mapping(uint => uint) public data;
function f() returns (uint, uint){
data[25] = 100;
//直接访问,通过访问器访问
return(data[25], this.data(25));
}
}
结构体
结构体的访问器也是同名的函数。访问器返回结果是结构体中的每个变量。
pragma solidity ^0.4.0;
contract StructGetter{
struct S{
uint a;
string b;
bytes32 c;
}
S public s = S(10, "Hello",hex"1234");
function f() returns (uint, bytes32){
var (a, b, c) = this.s();
return (a, c);
}
}
上例中,可以看出,结构体的访问器分别返回了S
中的a
,b
,c
三个变量值。但由于Solidity不支持通过external
的访问变长内容3,故上面的代码,通过f()
不能返回b
的值,会报错Type inaccessible dynamic type is not implicitly convertible
。但如果使用Remix,复制上述合约后,可以通过生成的默认访问器,访问到结构体内的所有变量值。
一个复杂的例子
下面是一个集合结构体,数组,映射的一个复杂例子。但访问器访问方式遵循前述的规则:
pragma solidity ^0.4.0;
contract Complex {
struct Data {
uint a;
bytes3 b;
mapping (uint => uint) map;
}
mapping (uint => mapping(bool => Data[])) public data;
Data[] internal arr;
function f() returns (uint, bytes3){
Data memory d = Data(1, 0x123);
arr.push(d);
data[0][true] = arr;
return this.data(0, true, 0);
}
}
上面代码中,data
状态变量的访问器,有三个参数。第一个参数是第一层映射的键uint
,第二个参数是映射内嵌映射的键类型bool
。由于两层映射最终映射到的是数组。故而,第三个参数是数组的序号值。访问器返回的类型是结构体类型Data
,所以上述代码将返回1
,0x000123
。
需要注意的是,访问器返回结果结构体内的映射map
,由于访问器没有较好的方式来提供访问,所以直接被忽略了。
另外上述的最终映射到的Data[]
必须先初始化,否则由于数组越界访问,会报错Exception during execution. (invalid opcode).
4。
关于作者
专注基于以太坊(Ethereum)的相关区块链(Blockchain)技术,了解以太坊,Solidity,Truffle,web3.js。
个人博客: http://tryblockchain.org
版权所有,转载注明出处
参考资料
-
关于getter特性的原文介绍 http://solidity.readthedocs.io/en/develop/contracts.html#getter-functions ↩
-
关于internal,external的可见性,详见这里。http://me.tryblockchain.org/solidity-function-advanced1.html ↩
-
https://ethereum.stackexchange.com/questions/6975/type-inaccessible-dynamic-type-is-not-implicitly-convertible ↩
-
Solidity中异常的定义。 http://www.tryblockchain.org/Solidity-Exceptions-%E5%BC%82%E5%B8%B8.html ↩
处于某些特定的环境下,可以看到评论框,欢迎留言交流^_^。