【Solidity】继承

继承

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

   X
 / |
Y  |
 \ |
   Z

根据 C3 线性化算法,继承顺序是从最底层的合约开始,逐层向上合并继承路径。具体步骤如下:

  1. 从最底层合约 Z 开始:

    • Z 继承自 YX
    • 继承顺序:[Z, Y, X]
  2. 合并继承路径:

    • Y 继承自 X
    • 继承顺序:[Y, X]
  3. 最终继承顺序:

    • 合并 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

  X
 / \
Y   A
|   |
|   B
 \ /
  Z

根据 C3 线性化算法,继承顺序是从最底层的合约开始,逐层向上合并继承路径。具体步骤如下:

  1. 从最底层合约 Z 开始:

    • Z 继承自 YB
    • 继承顺序:[Z, Y, B]
  2. 合并继承路径:

    • Y 继承自 X
    • B 继承自 AA 继承自 X
    • 继承顺序:[Y, X][B, A, X]
  3. 最终继承顺序:

    • 合并 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
    }
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JS.Huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值