Solidity极简入门: 10. 继承 父与子

这一讲,我们介绍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()
Baba合约成功重写了hip()和pop()

Baba合约成功重写了hip()和pop()

多重继承

solidity的合约可以继承多个合约。规则:

  1. 继承时要按辈分最高到最低的顺序排。比如我们写一个Erzi合约,继承Yeye合约和Baba合约,那么就要写成contract Erzi is Yeye, Baba,而不能写成contract Erzi is Baba, Yeye,不然就会报错。

  2. 如果某一个函数在多个继承的合约里都存在,比如例子中的hip()pop(),在子合约里必须重写,不然会报错。

  3. 重写在多个父合约中重名函数时,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”,并且还分别从YeyeBaba合约继承了yeye()baba()两个函数。

Erzi合约继承了baba()和yeye()
Erzi合约继承了baba()和yeye()

Erzi合约继承了baba()和yeye()

修饰器的继承

Solidity中的修饰器(Modifier)同样可以继承,用法与函数继承类似,在相应的地方加virtualoverride关键字即可。

构造函数的继承

子合约有两种方法即成父合约的构造函数。举个简单的例子,父合约A里面有一个状态变量a,并由构造函数的参数来确定:

// 构造函数的继承
abstract contract A {
    uint public a;

    constructor(uint _a) {
        a = _a;
    }
}
  1. 在继承时声明父构造函数的参数,例如:contract B is A(1)

  2. 在子合约的构造函数中声明构造函数的参数,例如:

contract C is A {
    constructor(uint _c) A(_c * _c) {}
}

总结

这一讲,我们介绍了solidity继承的基本用法,包括简单继承,多重继承,以及修饰器和构造函数的继承。