Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solidity中的多线继承 #67

Open
MagicalBridge opened this issue Jun 22, 2024 · 0 comments
Open

Solidity中的多线继承 #67

MagicalBridge opened this issue Jun 22, 2024 · 0 comments

Comments

@MagicalBridge
Copy link
Owner

Solidity中的继承这篇文章中,我介绍了solidity中关于继承的相关概念和例子。本篇文章,我们来一起探讨一个更加复杂的话题多线继承

基本概念

Solidity支持多线继承,即一个合约可以同时继承多个基类合约。这可以使合约代码更加简洁,更容易复用代码

让我们看一个简单的例子:

代码实现

pragma solidity ^0.8.24;

contract A {
    function foo() public pure virtual returns (string memory) {
        return "A";
    }
}

contract B {
    function bar() public pure virtual returns (string memory) {
        return "B";
    }
}

contract C is A, B {
    function foo() public pure override returns (string memory) {
        return "C";
    }
    
    function bar() public pure override returns (string memory) {
        return "C";
    }
    
    function baz() public pure returns (string memory) {
        return "C";
    }
}

在这个例子中,合约 C 继承了合约 AB。这意味着 C 合约拥有所有来自 AB 合约的函数和状态变量。

C 合约中,函数 foo()bar()override 关键字标记。这意味着 C 合约提供了这两个函数的自定义实现,而不是使用来自基类合约的实现。

函数 baz()C 合约的唯一新函数。

部署示例展示

image.png

我们只需要部署合约C,从打印的结果看,所有的输出结果都是符合预期的。

多线继承中存在的问题

  • 菱形继承问题:如果多个基类合约继承自同一个基类,则会出现菱形继承问题。在这种情况下,不清楚哪个基类合约的函数和状态变量应该优先使用。

  • 函数名冲突:如果多个基类合约定义了具有相同名称的函数,则会出现函数名冲突。在这种情况下,需要使用 override 关键字显式指定要使用的函数实现。

  • 代码复杂性:多线继承会使合约代码更加复杂,难以理解和维护。

其中菱形继承问题稍微复杂一些,我们单独拿出来说明一下。

菱形继承问题

菱形继承是指一个类同时继承自多个基类,而这些基类又存在继承关系的情况。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

contract X {
    function foo() public pure virtual returns (string memory) {
        return "X";
    }
    
    function bar() public pure virtual returns (string memory) {
        return "X";
    }
}

contract Y is X {
    function foo() public pure virtual  override returns (string memory) {
        return "Y";
    }
    function bar() public pure virtual  override returns (string memory) {
        return "Y";
    }
    function baz() public pure virtual returns (string memory) {
        return "Y";
    }
}

contract Z is X,Y {
    function foo() public pure override(X,Y) returns (string memory) {
        return "Z";
    }
    function bar() public pure override(X,Y) returns (string memory) {
        return "Z";
    }
    function baz() public pure override returns (string memory) {
        return "Z";
    }
}

部署之后的执行结果

image.png

关于继承的顺序问题

Solidity的继承方式是从最远的基合约到最近的基合约的顺序解决状态变量的初始化和布局;

上面代码中,Z继承了XY两个合约,需要将X写在前面,这是因为,X是最基础的合约,它没有继承任何的合约,Y继承了X合约,这部分的顺序一定要注意。

总结

在大多数情况下,建议使用单继承或接口来代替菱形继承。单继承更简单,更容易理解和维护。非必要不要使用多线继承。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant