Bootstrap

solidity高阶 -- 继承

       Solidity是一种面向区块链的智能合约编程语言,广泛应用于以太坊等区块链平台。继承是Solidity中一个非常重要的特性,它允许开发者通过创建子合约来扩展父合约的功能,从而实现代码的复用和层次化设计。本文将通过具体实例详细介绍Solidity语言中的继承机制。

注意:使用继承时请确保代码的正确性,以防丢失个人财产,在这里友情提示您,不要复制来源不明的solidity代码并进行部署。

        本文为自己梳理总结,如有不足还请指出,感谢包容。

        学习更多solidity知识请访问 Github -- solidity基础 ,更多实例在 Smart contract

 

1. 基本继承语法

        在 Solidity 中,通过is关键字来表明一个合约继承自另一个合约。例如,contract B is A 表示合约 B 继承自合约 A。被继承的合约(如合约 A)被称为父合约,继承的合约(如合约 B)被称为子合约。子合约可以访问父合约中所有非 private 的状态变量和函数。         

在Solidity中,继承使用is关键字来实现。子合约通过is关键字声明继承自父合约。例如:

contract Parent {
    function greet() public pure virtual returns (string memory) {
        return "Hello from Parent";
    }
}

contract Child is Parent {
    function greet() public pure override returns (string memory) {
        return "Hello from Child";
    }
}

在这个例子中,Child合约继承自Parent合约。Parent合约定义了一个greet函数,该函数被标记为virtual,表示它可以被子合约重写。Child合约通过override关键字重写了greet函数,从而改变了其行为。

 

2. 多重继承

Solidity支持多重继承,即一个合约可以继承多个父合约。在多重继承的情况下,如果多个父合约中存在同名函数,Solidity会按照继承列表中合约的顺序进行解析。例如:

contract Base1 {
    function hello() public pure virtual returns (string memory) {
        return "Hello from Base1";
    }
}

contract Base2 {
    function hello() public pure virtual returns (string memory) {
        return "Hello from Base2";
    }
}

contract Derived is Base1, Base2 {
    function hello() public pure override(Base1, Base2) returns (string memory) {
        return "Hello from Derived";
    }
}

在这个例子中,Derived合约同时继承了Base1Base2。由于Base1Base2都定义了一个hello函数,因此Derived合约需要明确地重写这个函数,并通过override(Base1, Base2)指明它覆盖了来自Base1Base2hello函数。

 

3. 构造函数的继承

在Solidity中,子合约可以调用父合约的构造函数。如果父合约有构造函数,子合约必须显式地调用它。例如:

contract Parent {
    string public name;

    constructor(string memory _name) {
        name = _name;
    }
}

contract Child is Parent {
    constructor(string memory _name) Parent(_name) {
        // Child-specific initialization
    }
}

在这个例子中,Child合约继承了Parent合约,并且在Child的构造函数中显式地调用了Parent的构造函数。

 

4. 访问修饰符与继承

Solidity中的访问修饰符(publicprivateinternalexternal)在继承中也有重要作用。例如:

contract Parent {
    function internalFunction() internal pure returns (string memory) {
        return "Internal from Parent";
    }

    function publicFunction() public pure returns (string memory) {
        return internalFunction();
    }
}

contract Child is Parent {
    function callInternal() public pure returns (string memory) {
        return internalFunction(); // 可以访问父合约的internal函数
    }
}

在这个例子中,Child合约可以访问Parent合约中的internal函数,因为internal函数在同一个合约族中是可访问的。

 

5. 虚函数与重写

在Solidity中,使用virtual关键字声明的函数可以被子合约重写。子合约通过override关键字来实现重写。例如:

contract Base {
    function sayHello() public pure virtual returns (string memory) {
        return "Hello from Base";
    }
}

contract Derived is Base {
    function sayHello() public pure override returns (string memory) {
        return "Hello from Derived";
    }
}

在这个例子中,Derived合约重写了Base合约中的sayHello函数。

 

6. 构造函数与继承

如果父合约有构造函数,子合约在构造时必须显式调用父合约的构造函数。例如:

contract Base {
    string public name;

    constructor(string memory _name) {
        name = _name;
    }
}

contract Derived is Base {
    constructor(string memory _name) Base(_name) {
        // 可以在这里添加子合约的初始化逻辑
    }
}

在这个例子中,Derived合约在构造时调用了Base合约的构造函数。

 

7. 多重继承与构造函数

如果一个合约继承了多个父合约,且这些父合约都有构造函数,子合约需要按照继承顺序显式调用这些父合约的构造函数。例如:

contract Base1 {
    string public name1;

    constructor(string memory _name1) {
        name1 = _name1;
    }
}

contract Base2 {
    string public name2;

    constructor(string memory _name2) {
        name2 = _name2;
    }
}

contract Derived is Base1, Base2 {
    constructor(string memory _name1, string memory _name2) Base1(_name1) Base2(_name2) {
        // 可以在这里添加子合约的初始化逻辑
    }
}

在这个例子中,Derived合约继承了Base1Base2,并且在构造时按照继承顺序调用了Base1Base2的构造函数。

 

8. 构造函数与继承的顺序

在多重继承的情况下,构造函数的调用顺序非常重要。Solidity会按照继承列表中合约的顺序从右到左调用父合约的构造函数。例如:

contract Base1 {
    string public name1;

    constructor(string memory _name1) {
        name1 = _name1;
    }
}

contract Base2 {
    string public name2;

    constructor(string memory _name2) {
        name2 = _name2;
    }
}

contract Derived is Base1, Base2 {
    constructor(string memory _name1, string memory _name2) Base1(_name1) Base2(_name2) {
        // 可以在这里添加子合约的初始化逻辑
    }
}

在这个例子中,Derived合约继承了Base1Base2,构造函数的调用顺序是Base2 -> Base1 -> Derived

 

9. 继承与状态变量

子合约可以访问父合约的状态变量。如果父合约的状态变量是public,子合约可以直接访问它。例如:

contract Base {
    uint public value;

    constructor(uint _value) {
        value = _value;
    }
}

contract Derived is Base {
    function getValue() public view returns (uint) {
        return value; // 直接访问父合约的public状态变量
    }
}

在这个例子中,Derived合约可以直接访问Base合约中的value状态变量。

 

10. 继承与事件

子合约可以继承父合约中定义的事件。例如:

contract Base {
    event Log(string message);

    function logMessage() public {
        emit Log("Message from Base");
    }
}

contract Derived is Base {
    function logDerivedMessage() public {
        emit Log("Message from Derived");
    }
}

在这个例子中,Derived合约继承了Base合约中的Log事件,并且可以在自己的函数中使用它。

 

11. 继承与修饰符

子合约可以继承父合约中定义的修饰符,并且可以在自己的函数中使用这些修饰符。例如:

contract Base {
    modifier onlyOwner() {
        require(msg.sender == address(this), "Not the owner");
        _;
    }

    function protectedFunction() public pure onlyOwner {
        return "Protected function";
    }
}

contract Derived is Base {
    function anotherProtectedFunction() public pure onlyOwner {
        return "Another protected function";
    }
}

在这个例子中,Derived合约继承了Base合约中的onlyOwner修饰符,并且可以在自己的函数中使用它。

 

        Solidity语言中的继承机制为智能合约的开发提供了强大的功能,使得代码复用和层次化设计成为可能。通过is关键字,子合约可以继承父合约的功能,并通过override关键字重写父合约的函数。此外,Solidity还支持多重继承、构造函数的继承、状态变量的访问、事件的继承以及修饰符的继承。开发者可以利用这些特性构建复杂且高效的智能合约系统。

 

;