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

By [DAO4Resilience](https://paragraph.com/@dao4resilience) · 2022-04-24

---

这一讲，我们介绍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()](https://storage.googleapis.com/papyrus_images/c8ec7e143b3c3194c4c2b17fea4b8aaa95430ec148881abb1b922489b2ec7392.png)

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”`，并且还分别从`Yeye`和`Baba`合约继承了`yeye()`和`baba()`两个函数。

![Erzi合约继承了baba()和yeye()](https://storage.googleapis.com/papyrus_images/e5cc0112b3a3809145fd69152786f62e7f9ea1315cb96ab237e9122fd45e4e96.png)

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

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

### 修饰器的继承

Solidity中的修饰器（Modifier）同样可以继承，用法与函数继承类似，在相应的地方加`virtual`和`override`关键字即可。

### 构造函数的继承

子合约有两种方法即成父合约的构造函数。举个简单的例子，父合约`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继承的基本用法，包括简单继承，多重继承，以及修饰器和构造函数的继承。

---

*Originally published on [DAO4Resilience](https://paragraph.com/@dao4resilience/solidity-10)*
