Solidity编程语言基础知识四(Solidity继承、抽象合约、接口和库)

15.Solidity继承

        继承可以理解为一个合约从另一个合约获取合约结构(除私有状态变量和私有函数)的过程,目的是为了实现代码复用,被继承者被称为基类合约或父合约,继承者被称为派生合约或子合约。

        子合约继承父合约时,在区块链上只有一个合约被创建,父合约的合约结构(除私有状态变量和私有函数)被编译到子合约中,可以理解为在父合约中编写的合约结构(除私有状态变量和私有函数)复制到子合约中后子合约再部署到区块链上。

合约继承声明格式如下:

contract ContractName is <parent contract list>{
  // 语句
}

字段

描述

contract

声明合约的关键字。

ContractName

自定义的合约名称。

is

继承关键字。

<parent contract list>

Solidity语言支持子合约同时继承多个父合约。<parent contract list>是指父合约名称列表,父合约名称间用逗号隔开。

    // 声明父合约
    contract ParentContract{
        // 声明状态变量
        string str = unicode"状态变量被调用";

        // 声明函数
        function fun() public pure returns(string memory){
            return unicode"函数被调用";
        }

        // 声明函数修改器
        modifier CheckNum(){
            require(false, unicode"函数修改器被调用");
            _;
        }

        // 声明事件
        event Log(string);

        // 声明自定义Error错误
        error err(string);

        // 声明结构体
        struct Student{
            string name;
            uint age;
        }

        // 声明状态类型
        enum Stauts{unpaid, shipped, received, evaluted}
    }

    // 声明子合约并继承ParentContract合约
    contract ChildrenContract is ParentContract{
        // 调用在父合约中声明的状态变量
        function aCallVar() public view returns(string memory){
            return str;
        }

        // 调用在父合约中声明的函数
        function bCallFun() public  pure returns(string memory){
            return fun();
        }

        // 调用在父合约中声明的函数修改器
        function cCallModifier() public pure CheckNum(){
            
        }

        // 调用在父合约中声明的事件
        function dCallEvent() public{
            emit Log(unicode"事件被调用");
        }

        // 调用在父合约中声明的自定义Error错误
        function eCallError() public pure{
            revert err(unicode"自定义Error错误被调用");
        }

        // 调用在父合约中声明的结构体
        function fCallStruct() public pure returns(Student memory){
            Student memory stu;
            stu.name = "Alice";
            stu.age = 20;

            return stu;
        }

        // 调用在父合约中声明的枚举类型
        function gCallEnum() public pure returns(Stauts){
            return Stauts.received;
        }
    }

15.1.重写

        重写是指子合约对父合约的合约结构进行重新编写,目的为了在父合约的合约结构无法满足需求时,子合约需要对这个合约结构进行改良来满足新的需求。Solidity语言支持重写的合约结构只有函数和函数修改器。

        允许被重写的合约结构需要被virtual关键字修饰;要重写父合约-合约结构的子合约-合约机构需要被override关键字修饰。

15.1.1.重写函数

  • 重写函数规则
    •  重写函数与被重写函数的名称要相同
    • 重写函数与被重写函数的输入参数类型和数量要相同
    • 重写函数与被重写函数的返回参数类型和数量要相同
    // 声明父合约
    contract Parent{
        // 声明无参被重写函数,被重写函数需要用virtual关键字修饰
        function test() public pure virtual returns(string memory){
            return unicode"父合约";
        }

        // 声明有参被重写函数,被重写函数需要用virtual关键字修饰
        function test(string memory _str) public pure virtual returns(string memory){
            // string.concat():将多个字符串组合成一个字符串
            string memory str = string.concat(unicode"父合约的输入参数为:", _str);

            return str;
        }
    }

    // 声明子合约
    contract Children is Parent{
        // 声明无参重写函数,重写函数需要用override关键字修饰
        // 父合约和子合约的test函数都无输入参数,返回参数都为string类型,则子合约的无参test函数会重写父合约的无参test函数
        function test() public pure override returns(string memory){
            return unicode"子合约";
        }

        // 声明有参重写函数,重写函数需要用override关键字修饰
        // 父合约和子合约的test函数的输入参数都为string类型,返回参数都为string类型,则子合约的有参test函数会重写父合约的有参test函数
        function test(string memory _str) public pure override returns(string memory){
            // string.concat():将多个字符串组合成一个字符串
            string memory str = string.concat(unicode"子合约的输入参数为:", _str);

            return str;
        }
    }
  • 函数可见性对重写的影响
    • 可见性为public的被重写函数,只可被public函数重写
    • 可见性为external的被重写函数,可被public或external函数重写
    • 可见性为internal的被重写函数,只可被internal函数重写
    • 可见性为private的函数不可同时被virtual关键字修饰,因此private函数不可被重写
    // 声明父合约
    contract Parent{
        // 声明可见性为public的被重写函数
        function pubFun() public pure virtual returns(string memory){
            return "parent: public pubFun";
        }

        // 声明可见性为external的被重写函数
        function extFun() external pure virtual returns(string memory){
            return "parent: external extFun";
        }

        // 声明可见性为internal的被重写函数
        function intFun() internal pure virtual returns(string memory){
            return "parent: internal intFun";
        }

        // private函数不可同时使用virtual关键字
        // function priFun() private pure virtual returns(string memory){
        //     return "parent: private priFun";
        // }
    }

    // 声明子合约
    contract Children is Parent{
        // 可见性为public的pubFun函数重写父合约的pubFun函数
        function pubFun() public pure override returns(string memory){
            return "children: public pubFun";
        }

        // 可见性为public的extFun函数重写父合约的extFun函数
        function extFun() public pure override returns(string memory){
            return "children: public extFun";
        }

        // 可见性为external的extFun函数重写父合约的extFun函数
        // function extFun() external pure override returns(string memory){
        //     return "children: external extFun";
        // }

        // 可见性为internal的intFun函数重写父合约的intFun函数
        function intFun() internal pure override returns(string memory){
            return "children: internal intFun";
        }
    }
  • 函数状态可变性对重写的影响
    • 状态可变性为pure的被重写函数,只可被pure函数重写
    • 状态可变性为view的被重写函数,可被pure或view函数重写
    • 状态可变性为nonpayable的被重写函数,可被pure、view或nonpayable函数重写
    • 状态可变性为payable的被重写函数,只可被payable函数重写
    // 声明父合约
    contract Parent{
        // 声明状态可变性为pure的被重写函数
        function pureFun() public pure virtual returns(string memory){
            return "parent: pure pureFun";
        }

        // 声明状态可变性为view的被重写函数
        function viewFun() public view virtual returns(string memory){
            return "parent: view viewFun";
        }

        // 声明状态可变性为nonpayable的被重写函数
        function nonpayableFun() public virtual returns(string memory){
            return "parent: nonpayable nonpayableFun";
        }

        // 声明状态可变性为payable的被重写函数
        function payableFun() public payable virtual returns(string memory){
            return "parent: payable payableFun";
        }
    }

    // 声明子合约
    contract Children is Parent{
        // 状态可变性为pure的pureFun函数重写父合约的pureFun函数
        function pureFun() public pure override returns(string memory){
            return "children: pure pureFun";
        }

        // 状态可变性为pure的viewFun函数重写父合约的viewFun函数
        function viewFun() public pure override returns(string memory){
            return "children: pure viewFun";
        }

        // 状态可变性为view的viewFun函数重写父合约的viewFun函数
        // function viewFun() public view override returns(string memory){
        //     return "children: view viewFun";
        // }

        // 状态可变性为pure的nonpayableFun函数重写父合约的nonpayableFun函数
        function nonpayableFun() public pure override returns(string memory){
            return "children: pure nonpayableFun";
        }

        // 状态可变性为view的nonpayableFun函数重写父合约的nonpayableFun函数
        // function nonpayableFun() public view override returns(string memory){
        //     return "children: view nonpayableFun";
        // }

        // 状态可变性为nonpayable的nonpayableFun函数重写父合约的nonpayableFun函数
        // function nonpayableFun() public override returns(string memory){
        //     return "children: nonpayable nonpayableFun";
        // }

        // 状态可变性为payable的payableFun函数重写父合约的payableFun函数
        function payableFun() public payable override returns(string memory){
            return "children: payable payab
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值