前言
其实呢,今天刚接触Using for的时候,我并没有看懂它的意思。官方的文档有些晦涩难懂,导致我也产生了它与import的区别这样的疑问。
使用
与import的联系与区别
先回答第二个问题,using A for B与import有什么区别?
import是讲某个合约contract或者某个库lib导入到当前文件,它是using的前提;import后,当前文件内可以引用被引入文件内定义的library或contract。
举个例子:
这里,如果没有先import,直接using,会报错。除非别的被import的文件再import了它。换句换说,就是
using的前提是需要直接或者间接的导入某个library.
Using for 如何使用
using A for B,这里A通常是某个library里面定义的某个方法,B是某种数据类型,这句话是把A方法绑定到B类型上,相当于给B类型附加了一个A方法。(也有翻译为附着库的)
在上面的例子中,将LibContract里定义的方法绑定到所有的数据类型。但是一般我们不会在所有的类型实例上都去调用LibContract的方法,应该是要按需using的,这里偷懒就写*。
在通俗一点的例子就是,
比如 using LibInt for uint,然后LibInt里面有定义一个toString方法。我们有一个uint a;那么可以这样调用a.toString(),toString方法在定义的时候,第一个参数会是一个uint类型的变量,表示调用者。
using A for B,A的函数的第一个参数必须和B的数据类型一致。
还有这个方法是可以重载的,你可以定义好几个同名的方法,但是第一个参数的类型不同,调用的时候自动的根据调用类型选择某一种方法。
实例1
pragma solidity ^0.4.16;
library Set {
struct Data { mapping(uint => bool) flags; }
function insert(Data storage self, uint value)
public
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value)
public
returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value)
public
view
returns (bool)
{
return self.flags[value];
}
}
contract C {
using Set for Set.Data;
Set.Data knownValues;
function register(uint value) public {
// 相当于Set.insert(knownValues, value)
require(knownValues.insert(value));
}
}
实例2:
pragma solidity ^0.4.16;
library Search {
function indexOf(uint[] storage self, uint value)
public
view
returns (uint)
{
for (uint i = 0; i < self.length; i++)
if (self[i] == value) return i;
return uint(-1);
}
}
contract C {
using Search for uint[];
uint[] data;
function append(uint value) public {
data.push(value);
}
function replace(uint _old, uint _new) public {
uint index = data.indexOf(_old);
if (index == uint(-1))
data.push(_new);
else
data[index] = _new;
}
}