这一讲,我们介绍solidity中的继承(inheritance),包括简单继承,多重继承,以及修饰器(modifier)和构造函数(constructor)的继承。
继承是面向对象编程很重要的组成部分,可以显著减少重复代码。如果把合约看作是对象的话,solidity也是面向对象的编程,也支持继承。
virtual: 父合约中的函数,如果希望子合约重写,需要加上virtual关键字。
override:子合约重写了父合约中的函数,需要加上override关键。
我们先写一个简单的爷爷合约Yeye,里面包含3个function: hip(), pop(), yeye(),返回值都是”Yeye”。
contract Yeye {
// 定义3个function: hip(), pop(), man(),返回值设为A。
function hip() public pure virtual returns (string memory){
return("Yeye");
}
function pop() public pure virtual returns (string memory){
return("Yeye");
}
function yeye() public pure virtual returns (string memory){
return("Yeye");
}
}
我们再定义一个爸爸合约Baba,让他继承Yeye合约,语法就是contract Baba is Yeye,非常直观。在Baba合约里,我们重写一下hip()和pop()这两个函数,加上override关键字,并将他们的返回值改为”Baba”;并且加一个新的函数baba,返回值也是”Baba”。
contract Baba is Yeye{
// 继承两个function: hip()和pop(),返回值改为B。
function hip() public pure virtual override returns (string memory){
return("Baba");
}
function pop() public pure virtual override returns (string memory){
return("Baba");
}
function baba() public pure virtual returns (string memory){
return("Baba");
}
}
我们部署合约,可以看到Baba合约里有4个函数,其中hip()和pop()的返回值被成功改写成”Baba”,而继承来的yeye()的返回值仍然是”Yeye”。

Baba合约成功重写了hip()和pop()
solidity的合约可以继承多个合约。规则:
继承时要按辈分最高到最低的顺序排。比如我们写一个
Erzi合约,继承Yeye合约和Baba合约,那么就要写成contract Erzi is Yeye, Baba,而不能写成contract Erzi is Baba, Yeye,不然就会报错。如果某一个函数在多个继承的合约里都存在,比如例子中的
hip()和pop(),在子合约里必须重写,不然会报错。重写在多个父合约中重名函数时,override关键字后面要加上父合约名字,例如
override(Yeye, Baba)。
例子:
contract Erzi is Yeye, Baba{
// 继承两个function: hip()和pop(),返回值改为B。
function hip() public pure virtual override(Yeye, Baba) returns (string memory){
return("Erzi");
}
function pop() public pure virtual override(Yeye, Baba) returns (string memory){
return("Erzi");
}
}
我们可以看到,Erzi合约里面重写了hip()和pop()两个函数,将返回值改为”Erzi”,并且还分别从Yeye和Baba合约继承了yeye()和baba()两个函数。

Erzi合约继承了baba()和yeye()
Solidity中的修饰器(Modifier)同样可以继承,用法与函数继承类似,在相应的地方加virtual和override关键字即可。
子合约有两种方法即成父合约的构造函数。举个简单的例子,父合约A里面有一个状态变量a,并由构造函数的参数来确定:
// 构造函数的继承
abstract contract A {
uint public a;
constructor(uint _a) {
a = _a;
}
}
在继承时声明父构造函数的参数,例如:
contract B is A(1)在子合约的构造函数中声明构造函数的参数,例如:
contract C is A {
constructor(uint _c) A(_c * _c) {}
}
这一讲,我们介绍了solidity继承的基本用法,包括简单继承,多重继承,以及修饰器和构造函数的继承。
