接口的存在就是为了合约之间的通信。
有两种实现方式:抽象合约 和 接口
一、抽象合约
抽象函数是没有函数体的的函数。如下:
pragma solidity ^0.4.0;
contract Feline {
function utterance() returns (bytes32);
}
这样的合约不能通过编译,即使合约内也包含一些正常的函数。但它们可以做为基合约被继承。
pragma solidity ^0.4.0;
contract Feline {
function utterance()
returns (bytes32);
function getContractName() returns (string){
return "Feline";
}
}
contract Cat is Feline {
function utterance() returns (bytes32) {
return "miaow";
}
}
如果一个合约从一个抽象合约里继承,但却没实现所有函数,那么它也是一个抽象合约。
如何通过抽象合约实现接口功能?
如果contract B要使用contract A的方法或数据,本质上:
二、接口
接口与抽象合约类似,与之不同的是,接口内没有任何函数是已实现的,同时还有如下限制:
接口基本上限制为合约ABI定义可以表示的内容,ABI和接口定义之间的转换应该是可能的,不会有任何信息丢失。
注意:
1、在两个.sol文件中都声明接口,或者两个合约写到一个.sol文件里,那就只要声明一次;
2、在一个合约中实现METHOD_A,该合同必须继承自接口interfaceContract;
3、在另一个合约中创建一个interfaceContract实例,该实例接受实现接口的合约的地址;
4、通过这个实例调用目标合约的方法,获取目标合约的数据;
实例:
被调用合约 InterfaceImpContract
pragma solidity ^0.4.16;
interface interfaceContract {
function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData);
}
contract InterfaceImplContract is interfaceContract {
event Receive(address from, uint256 value, address token, bytes extraData);
function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) {
Receive(_from,_value,_token,_extraData);
}
}
调用合约 RemoteContract
pragma solidity ^0.4.16;
interface interfaceContract {
function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData);
}
contract RemoteContract {
function func(address _addr, uint _value) {
//注意这里的_addr参数,需要填写tokenRecipient合约的地址。这里加载已经存在的智能合约。如何合约不存在会报错回滚。
interfaceContract _interfaceContract = interfaceContract(_addr);
_interfaceContract.receiveApproval(msg.sender, _value, address(this), "这是一些信息");
}
}
注意这里调用 func(address _addr, uint _value)方法时,传递的参数_addr,在下面的代码中,用来加载合约interfaceContract _interfaceContract = interfaceContract(_addr); 所以addr必须传递合约地址。并且这个合约地址是interfaceContract的实现类的合约地址。也就是第一步创建的InterfaceImplContract 合约的地址。
如果传递的_addr参数错误,调用失败。它将回滚所有已执行的功能。也就是这个方法会回滚。
这里部署时,只需部署RemoteContract 即可。不用管接口。接口只是为了声明。