接口
如果我们的合约需要和区块链上的其他的合约会话,则需先定义一个 interface (接口)。
例子:
contract LuckyNumber {
mapping(address => uint) numbers;
function setNum(uint _num) public {
numbers[msg.sender] = _num;
}
function getNum(address _myAddress) public view returns (uint) {
return numbers[_myAddress];
}
}这是个很简单的合约,你可以用它存储自己的幸运号码,并将其与你的地址关联。 这样其他人就可以通过你的地址查找你的幸运号码了。
现在假设我们有一个外部合约,使用 getNum 函数可读取其中的数据。
首先,我们定义 LuckyNumber 合约的 interface名为 NumberInterface,此处我们可以使用interface关键字,但是仍然可以使用contract关键字并在接口名中带有Interface:
contract NumberInterface {
function getNum(address _myAddress) public view returns (uint);
}从例子上来看,这个过程虽然看起来像在定义一个合约,但其并不一样:
首先,我们只声明了要与之交互的函数 —— 在本例中为
getNum—— 在其中我们没有使用到任何其他的函数或状态变量。其次,我们并没有使用大括号
{和}定义函数体,我们单单用分号;结束了函数声明。这使它看起来像一个合约框架。
在Solidity 0.6.0 之前的编译器其实就是靠这些特征认出它是一个接口的。(Solidity 0.6.x 中引入了Interface关键字)
在我们的 App 代码中使用这个接口,合约就知道其他合约的函数是怎样的,应该如何调用,以及可期待什么类型的返回值。
实战练习
为了增加我们区块链宠物游戏的趣味性,我们也可以让我们的宠物与其它宠物进行配对生成神兽。比如我们可以与以太坊区块链上最火的一款宠物 CryptoKitties 进行配对。
为了实现这个功能,我们要读出 CryptoKitties 智能合约中的 kittyDna。这些数据是公开存储在区块链上的。
我们已经为你查看过了 CryptoKitties 的源代码,并且找到了一个名为 getKitty 的函数,它返回所有的加密猫的数据,包括它的“基因”。我们的宠物游戏要用它生成新的宠物。
该函数如下所示:
function getKitty(uint256 _id) external view returns (
bool isGestating,
bool isReady,
uint256 cooldownIndex,
uint256 nextActionAt,
uint256 siringWithId,
uint256 birthTime,
uint256 matronId,
uint256 sireId,
uint256 generation,
uint256 genes
) {
Kitty storage kit = kitties[_id];
// if this variable is 0 then it's not gestating
isGestating = (kit.siringWithId != 0);
isReady = (kit.cooldownEndBlock <= block.number);
cooldownIndex = uint256(kit.cooldownIndex);
nextActionAt = uint256(kit.cooldownEndBlock);
siringWithId = uint256(kit.siringWithId);
birthTime = uint256(kit.birthTime);
matronId = uint256(kit.matronId);
sireId = uint256(kit.sireId);
generation = uint256(kit.generation);
genes = kit.genes;
}现在我们知道这个函数长什么样的了,就可以用它来创建一个接口:
1.定义一个名为 KittyInterface 的接口。
2.在interface里定义 getKitty 函数(可以复制/粘贴上面例子中的函数,但是不粘贴函数体的代码),仿照上面的例子,在函数声明完成之后用分号结束。


