11.1 抽象合約
抽象合約的形式為:
abstract contract A {
function add(uint _a, uint _b) public pure virtual returns (uint);
}
- 抽象合約在聲明時(shí)需要在前面加上關(guān)鍵字
abstract。 - 如果合約中最少存在一個(gè)未實(shí)現(xiàn)函數(shù),則合約必須聲明為抽象合約,否則編譯不通過(guò)。
- 為實(shí)現(xiàn)的函數(shù)必須加上
virtual關(guān)鍵字,以便子合約重寫(xiě),否則編譯不通過(guò)。 - 未實(shí)現(xiàn)函數(shù)以
;替換代碼塊。 - 繼承抽象合約的子合約,如果沒(méi)有全部實(shí)現(xiàn)父合約中所有未實(shí)現(xiàn)方法,則必須也聲明為抽象合約,否則編譯不通過(guò):
abstract contract B is A {}
- 子合約實(shí)現(xiàn)了所有未實(shí)現(xiàn)函數(shù),則無(wú)須聲明為抽象合約:
contract C is A {
function add(uint _a, uint _b) public pure override virtual returns (uint) {
return _a + _b;
}
11.2 接口
接口類(lèi)似于抽象合約,但它不實(shí)現(xiàn)任何功能。
11.2.1 定義一個(gè)接口
一個(gè)計(jì)算器,包含加和減兩個(gè)未實(shí)現(xiàn)函數(shù):
interface Calculator {
function add(uint _x, uint _y) external returns (uint);
function sub(uint _x, uint _y) external returns (uint);
}
說(shuō)明:
- 接口定義類(lèi)似于合約,只不過(guò)使用
interface作為關(guān)鍵詞。 - 接口中的所有函數(shù)都必須為未實(shí)現(xiàn)函數(shù)。
- 接口中不能包含狀態(tài)變量。
- 接口中的未實(shí)現(xiàn)函數(shù)必須為
external。
11.2.2 接口的繼承
繼承Calculator接口,添加兩個(gè)事件。
interface CalculatorEvent is Calculator {
event Add(uint x, uint y, uint z);
event Sub(uint x, uint y, uint z);
}
11.2.3 合約實(shí)現(xiàn)接口
如果未完全實(shí)現(xiàn)接口中所有的未實(shí)現(xiàn)函數(shù),則合約必須聲明為抽象合約:
abstract contract A is CalculatorEvent {
function add(uint _x, uint _y) external returns (uint) {
uint r = _x + _y;
emit Add(_x, _y, r);
return r;
}
}
實(shí)現(xiàn)了所有的未實(shí)現(xiàn)函數(shù),則無(wú)須添加abstract關(guān)鍵字:
contract C is A{
function sub(uint _x, uint _y) external returns (uint) {
uint r = _x - _y;
emit Add(_x, _y, r);
return r;
}
}
11.2.4 接口的使用
如果我們知道一個(gè)合約實(shí)現(xiàn)了CalculatorEvent接口,我們不需要知道它具體代碼實(shí)現(xiàn),就可以與它交互。例如:
contract D {
CalculatorEvent sss = CalculatorEvent(0xAb0b06f11dFC8FD18ef6b8eC4A8dEA026A136506);
function add(uint _x, uint _y) public returns (uint) {
return sss.add(_x, _y);
}
}
11.2.5 接口的重要性
雖然接口不實(shí)現(xiàn)任何功能,但它非常重要。接口是智能合約的骨架,定義了合約的功能以及如何觸發(fā)它們:如果智能合約實(shí)現(xiàn)了某種接口(比如ERC20或ERC721),其他Dapps和智能合約就知道如何與它交互。因?yàn)榻涌谔峁┝藘蓚€(gè)重要的信息:
合約里每個(gè)函數(shù)的
bytes4選擇器,以及函數(shù)簽名函數(shù)名(每個(gè)參數(shù)類(lèi)型)。接口id(更多信息見(jiàn)EIP165)
另外,接口與合約ABI(Application Binary Interface)等價(jià),可以相互轉(zhuǎn)換:編譯接口可以得到合約的ABI,利用abi-to-sol工具也可以將ABI json文件轉(zhuǎn)換為接口sol文件。