接口
在 Solidity
中,接口、抽象合约、与合约的抽象程度大致如下:
接口仅定义了需要实现的外部接口函数。抽象合约、具体合约可以实现接口。抽象合约中可能还存在未具体实现的虚函数,或者待决定的构造函数参数等。
具体合约可以继承于抽象合约。当具体合约继承于抽象合约时,必须实现抽象合约中未实现的虚函数,或者确定抽象合约中未确定的构造函数参数。
接口声明
接口与抽象合约或者具体合约不同,它不能实现任何函数,并且:
- 它是最抽象的最高层,接口可以继承其他接口,但是不能继承其他合约(无论是抽象合约还是具体合约)
- 对于函数,接口仅能声明未实现的外部(
external
)函数接口 - 接口类似于程序之间的协议,它只能被合约实现,而不能被具体实例化,因此无
constructor
- 同3,不能声明状态变量
- 同3,不能声明函数修饰符
- 可以声明结构体、枚举,因为在定义的接口中,可能会使用到这些结构体、枚举
Interfaces.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.1 <0.9.0;
/// @title 打招呼接口
interface SayHi {
// 可以声明枚举
enum Language {
English,
Chinese,
French,
German
}
// 可以声明结构体
struct Contry {
string name;
Language lang;
}
// 声明外部接口函数,默认为 virtual 函数,virtual 关键字可省略
function sayHi() external virtual returns (string memory);
}
接口中的函数默认且必须为虚函数,virtual
关键字可以省略。
接口实现
使用 is
关键字,来标识某个合约实现了某个接口:
InterfacesImpl.sol
// 实现接口 SayHi
contract Friend is SayHi {
function sayHi() external pure returns (string memory) {
return "Hi";
}
}
接口继承
接口可以继承另一个接口:
InterfacesImpl.sol
// 接口继承接口 SayHi
interface People is SayHi {
}
一个接口同样可以继承多个接口:
InterfacesImpl.sol
// 继承多个接口
interface SayHi1 {
function sayHi() external returns (string memory);
}
interface SayHi2 {
function sayHi() external returns (string memory);
}
interface People2 is SayHi1, SayHi2 {
function sayHi() external override(SayHi1, SayHi2) returns (string memory);
}
当多个父接口具有相同签名及返回类型的函数时,需要显式地使用 override
关键字,重新声明该外部接口。