【Solidity】继承

打印 上一主题 下一主题

主题 507|帖子 507|积分 1521

继承

Solidity 中使用 is 关键字实现继承:
  1. contract Father {
  2.     function getNumber() public pure returns (uint) {
  3.         return 10;
  4.     }
  5.     function getNumber2() public pure virtual returns (uint) {
  6.         return 20;
  7.     }
  8. }
  9. contract Son is Father {}
复制代码
现在 Son 就可以调用 Father 的 getNumber、getNumber2 方法啦



函数重写

对于父合约中用 virtual 修饰的方法,可以在子合约中改用 override 修饰 并重写方法的内容:
  1. contract Father {
  2.     function getNumber() public pure returns (uint) {
  3.         return 10;
  4.     }
  5.     function getNumber2() public pure virtual returns (uint) {
  6.         return 20;
  7.     }
  8. }
  9. contract Son is Father {
  10.     function getNumber2() public pure override returns (uint) {
  11.         return 40;
  12.     }
  13. }
复制代码



多级继承

  1. contract Father {
  2.     function getNumber() public pure returns (uint) {
  3.         return 10;
  4.     }
  5.     function getNumber2() public pure virtual returns (uint) {
  6.         return 20;
  7.     }
  8.     function getNumber3() public pure virtual returns (uint) {
  9.         return 30;
  10.     }
  11. }
  12. contract Son is Father {
  13.     function getNumber2() public pure override returns (uint) {
  14.         return 40;
  15.     }
  16.     // 用 virtual 和 override 同时修饰方法
  17.     function getNumber3() public pure virtual override returns (uint) {
  18.         return 50;
  19.     }
  20. }
  21. contract GrandSon is Son {
  22.     function getNumber3() public pure override returns (uint) {
  23.         return 60;
  24.     }
  25. }
复制代码



多重继承

在 Solidity 中,继承次序通过 C3 线性化算法确定。这个算法确保继承关系是一个有向无环图(DAG),并逼迫一个特定的继承次序。
demo1
  1.    X
  2. / |
  3. Y  |
  4. \ |
  5.    Z
复制代码
根据 C3 线性化算法,继承次序是从最底层的合约开始,逐层向上合并继承路径。详细步调如下:

  • 从最底层合约 Z 开始:

    • Z 继承自 Y 和 X。
    • 继承次序:[Z, Y, X]。

  • 合并继承路径:

    • Y 继承自 X。
    • 继承次序:[Y, X]。

  • 最终继承次序:

    • 合并 Z 的继承次序 [Z, Y, X] 和 Y 的继承次序 [Y, X]。
    • 确保每个合约只出现一次,而且遵循继承关系。
    • 最终继承次序为:[Z, Y, X]。

  1. contract X {
  2.     function foo() public virtual returns (string memory) {
  3.         return "X";
  4.     }
  5. }
  6. contract Y is X {
  7.     function foo() public virtual override returns (string memory) {
  8.         return "Y";
  9.     }
  10. }
  11. // 根据继承顺序, 先 X 后 Y;  若遇平级, 则顺序随意
  12. contract Z is X, Y {
  13.     // override 里面的顺序无所谓
  14.     function foo() public pure override(Y, X) returns (string memory) {
  15.         return "Z";
  16.     }
  17. }
复制代码
demo2
  1.   X
  2. / \
  3. Y   A
  4. |   |
  5. |   B
  6. \ /
  7.   Z
复制代码
根据 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]。

  1. contract X {
  2.     function foo() public virtual returns (string memory) {
  3.         return "X";
  4.     }
  5. }
  6. contract Y is X {
  7.     function foo() public virtual override returns (string memory) {
  8.         return "Y";
  9.     }
  10. }
  11. contract A is X {
  12.     function foo() public virtual override returns (string memory) {
  13.         return "A";
  14.     }
  15. }
  16. contract B is A {
  17.     function foo() public virtual override returns (string memory) {
  18.         return "B";
  19.     }
  20. }
  21. contract Z is Y, B {
  22.     function foo() public pure override(Y, B) returns (string memory) {
  23.         return "Z";
  24.     }
  25. }
复制代码



调用父合约的构造函数

  1. contract A {
  2.     string public name;
  3.     constructor(string memory _name) {
  4.         name = _name;
  5.     }
  6. }
  7. contract B {
  8.     uint public number;
  9.     constructor(uint _number) {
  10.         number = _number;
  11.     }
  12. }
  13. // demo 1 - 在构造函数后面调用基类构造函数
  14. contract C is A, B {
  15.     constructor(string memory _name, uint _number) A(_name) B(_number) {}
  16. }
  17. // demo 2 - 在合约定义时调用基类构造函数
  18. contract D is A("Hello"), B(42) {}
  19. // demo 3 - 混合使用 demo 1 和 2 的方法
  20. contract E is A("Hello"), B {
  21.     constructor(uint _number) B(_number) {}
  22. }
复制代码
构造函数的调用次序:先继承的父合约 → 后继承的父合约 → 当前合约
以是,demo 1 是 A → B → C、 demo 2 是 A → B → D、 demo 3 是 A → B → E



调用父合约的方法

  1. contract A {
  2.     event Log(string message);
  3.     function func() public virtual {
  4.         emit Log("A.func");
  5.     }
  6. }
  7. contract B is A {
  8.     function func() public virtual override {
  9.         emit Log("B.func");
  10.         // 方法 1 - 通过 super 调用
  11.         super.func(); // A
  12.     }
  13. }
  14. contract C is A {
  15.     function func() public virtual override {
  16.         emit Log("C.func");
  17.         // 方法 2 - 通过合约调用
  18.         A.func(); // A
  19.     }
  20. }
  21. contract D is B, C {
  22.         // 方法 1 和方法 2 的区别
  23.     function func() public override(B, C) {
  24.         C.func(); // C - A
  25.         B.func(); // B - A
  26.         A.func(); // A
  27.     }
  28.     function funcD() public {
  29.         super.func(); // C - B - A
  30.     }
  31. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

徐锦洪

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表