继承
Solidity 中使用 is 关键字实现继承:
- contract Father {
- function getNumber() public pure returns (uint) {
- return 10;
- }
- function getNumber2() public pure virtual returns (uint) {
- return 20;
- }
- }
- contract Son is Father {}
复制代码 现在 Son 就可以调用 Father 的 getNumber、getNumber2 方法啦
函数重写
对于父合约中用 virtual 修饰的方法,可以在子合约中改用 override 修饰 并重写方法的内容:
- contract Father {
- function getNumber() public pure returns (uint) {
- return 10;
- }
- function getNumber2() public pure virtual returns (uint) {
- return 20;
- }
- }
- contract Son is Father {
- function getNumber2() public pure override returns (uint) {
- return 40;
- }
- }
复制代码
多级继承
- contract Father {
- function getNumber() public pure returns (uint) {
- return 10;
- }
- function getNumber2() public pure virtual returns (uint) {
- return 20;
- }
- function getNumber3() public pure virtual returns (uint) {
- return 30;
- }
- }
- contract Son is Father {
- function getNumber2() public pure override returns (uint) {
- return 40;
- }
- // 用 virtual 和 override 同时修饰方法
- function getNumber3() public pure virtual override returns (uint) {
- return 50;
- }
- }
- contract GrandSon is Son {
- function getNumber3() public pure override returns (uint) {
- return 60;
- }
- }
复制代码
多重继承
在 Solidity 中,继承次序通过 C3 线性化算法确定。这个算法确保继承关系是一个有向无环图(DAG),并逼迫一个特定的继承次序。
demo1:
根据 C3 线性化算法,继承次序是从最底层的合约开始,逐层向上合并继承路径。详细步调如下:
- 从最底层合约 Z 开始:
- Z 继承自 Y 和 X。
- 继承次序:[Z, Y, X]。
- 合并继承路径:
- 最终继承次序:
- 合并 Z 的继承次序 [Z, Y, X] 和 Y 的继承次序 [Y, X]。
- 确保每个合约只出现一次,而且遵循继承关系。
- 最终继承次序为:[Z, Y, X]。
- contract X {
- function foo() public virtual returns (string memory) {
- return "X";
- }
- }
- contract Y is X {
- function foo() public virtual override returns (string memory) {
- return "Y";
- }
- }
- // 根据继承顺序, 先 X 后 Y; 若遇平级, 则顺序随意
- contract Z is X, Y {
- // override 里面的顺序无所谓
- function foo() public pure override(Y, X) returns (string memory) {
- return "Z";
- }
- }
复制代码 demo2:
根据 C3 线性化算法,继承次序是从最底层的合约开始,逐层向上合并继承路径。详细步调如下:
- 从最底层合约 Z 开始:
- Z 继承自 Y 和 B。
- 继承次序:[Z, Y, B]。
- 合并继承路径:
- Y 继承自 X。
- B 继承自 A,A 继承自 X。
- 继承次序:[Y, X] 和 [B, A, X]。
- 最终继承次序:
- 合并 Z 的继承次序 [Z, Y, B] 和 Y 的继承次序 [Y, X] 以及 B 的继承次序 [B, A, X]。
- 确保每个合约只出现一次,而且遵循继承关系。
- 最终继承次序为:[Z, Y, B, A, X]。
- contract X {
- function foo() public virtual returns (string memory) {
- return "X";
- }
- }
- contract Y is X {
- function foo() public virtual override returns (string memory) {
- return "Y";
- }
- }
- contract A is X {
- function foo() public virtual override returns (string memory) {
- return "A";
- }
- }
- contract B is A {
- function foo() public virtual override returns (string memory) {
- return "B";
- }
- }
- contract Z is Y, B {
- function foo() public pure override(Y, B) returns (string memory) {
- return "Z";
- }
- }
复制代码
调用父合约的构造函数
- contract A {
- string public name;
- constructor(string memory _name) {
- name = _name;
- }
- }
- contract B {
- uint public number;
- constructor(uint _number) {
- number = _number;
- }
- }
- // demo 1 - 在构造函数后面调用基类构造函数
- contract C is A, B {
- constructor(string memory _name, uint _number) A(_name) B(_number) {}
- }
- // demo 2 - 在合约定义时调用基类构造函数
- contract D is A("Hello"), B(42) {}
- // demo 3 - 混合使用 demo 1 和 2 的方法
- contract E is A("Hello"), B {
- constructor(uint _number) B(_number) {}
- }
复制代码 构造函数的调用次序:先继承的父合约 → 后继承的父合约 → 当前合约
以是,demo 1 是 A → B → C、 demo 2 是 A → B → D、 demo 3 是 A → B → E
调用父合约的方法
- contract A {
- event Log(string message);
- function func() public virtual {
- emit Log("A.func");
- }
- }
- contract B is A {
- function func() public virtual override {
- emit Log("B.func");
- // 方法 1 - 通过 super 调用
- super.func(); // A
- }
- }
- contract C is A {
- function func() public virtual override {
- emit Log("C.func");
- // 方法 2 - 通过合约调用
- A.func(); // A
- }
- }
- contract D is B, C {
- // 方法 1 和方法 2 的区别
- function func() public override(B, C) {
- C.func(); // C - A
- B.func(); // B - A
- A.func(); // A
- }
- function funcD() public {
- super.func(); // C - B - A
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |