Solidity 小白教程:13. 继承

news2025/1/11 4:21:39

Solidity 小白教程:13. 继承

这一讲,我们介绍solidity中的继承(inheritance),包括简单继承,多重继承,以及修饰器(modifier)和构造函数(constructor)的继承。

继承

继承是面向对象编程很重要的组成部分,可以显著减少重复代码。如果把合约看作是对象的话,solidity也是面向对象的编程,也支持继承。

规则

  • virtual: 父合约中的函数,如果希望子合约重写,需要加上virtual关键字。
  • override:子合约重写了父合约中的函数,需要加上override关键字。

注意:用override修饰public变量,会重写与变量同名的getter函数,例如:

mapping(address => uint256) public override balanceOf;

简单继承

我们先写一个简单的爷爷合约Yeye,里面包含 1 个Log事件和 3 个function: hip(), pop(), yeye(),输出都是”Yeye”。

contract Yeye {
    event Log(string msg);

    // 定义3个function: hip(), pop(), man(),Log值为Yeye。
    function hip() public virtual{
        emit Log("Yeye");
    }

    function pop() public virtual{
        emit Log("Yeye");
    }

    function yeye() public virtual {
        emit Log("Yeye");
    }
}

我们再定义一个爸爸合约Baba,让他继承Yeye合约,语法就是contract Baba is Yeye,非常直观。在Baba合约里,我们重写一下hip()pop()这两个函数,加上override关键字,并将他们的输出改为**”Baba”;并且加一个新的函数baba**,输出也是**”Baba”**。

contract Baba is Yeye{
    // 继承两个function: hip()和pop(),输出改为Baba。
    function hip() public virtual override{
        emit Log("Baba");
    }

    function pop() public virtual override{
        emit Log("Baba");
    }

    function baba() public virtual{
        emit Log("Baba");
    }
}

我们部署合约,可以看到Baba合约里有 4 个函数,其中hip()pop()的输出被成功改写成”Baba”,而继承来的yeye()的输出仍然是”Yeye”

多重继承

solidity的合约可以继承多个合约。规则:

  1. 继承时要按辈分最高到最低的顺序排。比如我们写一个Erzi合约,继承Yeye合约和Baba合约,那么就要写成contract Erzi is Yeye, Baba,而不能写成contract Erzi is Baba, Yeye,不然就会报错。
  2. 如果某一个函数在多个继承的合约里都存在,比如例子中的hip()pop(),在子合约里必须重写,不然会报错。
  3. 重写在多个父合约中都重名的函数时,override关键字后面要加上所有父合约名字,例如override(Yeye, Baba)

例子:

contract Erzi is Yeye, Baba{
    // 继承两个function: hip()和pop(),输出值为Erzi。
    function hip() public virtual override(Yeye, Baba){
        emit Log("Erzi");
    }

    function pop() public virtual override(Yeye, Baba) {
        emit Log("Erzi");
    }

我们可以看到,Erzi合约里面重写了hip()pop()两个函数,将输出改为”Erzi”,并且还分别从YeyeBaba合约继承了**yeye()baba()**两个函数。

修饰器的继承

Solidity中的修饰器(Modifier)同样可以继承,用法与函数继承类似,在相应的地方加virtualoverride关键字即可。

contract Base1 {
    modifier exactDividedBy2And3(uint _a) virtual {
        require(_a % 2 == 0 && _a % 3 == 0);
        _;
    }
}

contract Identifier is Base1 {

    //计算一个数分别被2除和被3除的值,但是传入的参数必须是2和3的倍数
    function getExactDividedBy2And3(uint _dividend) public exactDividedBy2And3(_dividend) pure returns(uint, uint) {
        return getExactDividedBy2And3WithoutModifier(_dividend);
    }

    //计算一个数分别被2除和被3除的值
    function getExactDividedBy2And3WithoutModifier(uint _dividend) public pure returns(uint, uint){
        uint div2 = _dividend / 2;
        uint div3 = _dividend / 3;
        return (div2, div3);
    }
}

Identifier合约可以直接在代码中使用父合约中的exactDividedBy2And3修饰器,也可以利用override关键字重写修饰器:

modifier exactDividedBy2And3(uint _a) override {
        _;
        require(_a % 2 == 0 && _a % 3 == 0);
    }

构造函数的继承

子合约有两种方法继承父合约的构造函数。举个简单的例子,父合约A里面有一个状态变量a,并由构造函数的参数来确定:

// 构造函数的继承
abstract contract A {
    uint public a;

    constructor(uint _a) {
        a = _a;
    }
}
  1. 在继承时声明父构造函数的参数,例如:contract B is A(1)
  2. 在子合约的构造函数中声明构造函数的参数,例如:
contract C is A {
    constructor(uint _c) A(_c * _c) {}
}

调用父合约的函数

子合约有两种方式调用父合约的函数,直接调用和利用super关键字。

  1. 直接调用:子合约可以直接用父合约名.函数名()的方式来调用父合约函数,例如Yeye.pop()
function callParent() public{
        Yeye.pop();
    }
  1. super关键字:子合约可以利用super.函数名()来调用最近的父合约函数。solidity继承关系按声明时从右到左的顺序是:contract Erzi is Yeye, Baba,那么Baba是最近的父合约,super.pop()将调用Baba.pop()而不是Yeye.pop()
function callParentSuper() public{
        // 将调用最近的父合约函数,Baba.pop()
        super.pop();
    }

钻石继承

在面向对象编程中,钻石继承(菱形继承)指一个派生类同时有两个或两个以上的基类。
在多重+菱形继承链条上使用super关键字时,需要注意的是使用super会调用继承链条上的每一个合约的相关函数,而不是只调用最近的父合约。
我们先写一个合约God,再写AdamEve两个合约继承God合约,最后让创建合约people继承自AdamEve,每个合约都有foobar两个函数。

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

/* 继承树:
  God
 /  \
Adam Eve
 \  /
people
*/

contract God {
    event Log(string message);

    function foo() public virtual {
        emit Log("God.foo called");
    }

    function bar() public virtual {
        emit Log("God.bar called");
    }
}

contract Adam is God {
    function foo() public virtual override {
        emit Log("Adam.foo called");
    }

    function bar() public virtual override {
        emit Log("Adam.bar called");
        super.bar();
    }
}

contract Eve is God {
    function foo() public virtual override {
        emit Log("Eve.foo called");
        Eve.foo();
    }

    function bar() public virtual override {
        emit Log("Eve.bar called");
        super.bar();
    }
}

contract people is Adam, Eve {
    function foo() public override(Adam, Eve) {
        super.foo();
    }

    function bar() public override(Adam, Eve) {
        super.bar();
    }
}

在这个例子中,调用合约people中的super.bar()会依次调用EveAdam,最后是God合约。
虽然EveAdam都是God的子合约,但整个过程中God合约只会被调用一次。原因是 Solidity 借鉴了 Python 的方式,强制一个由基类构成的 DAG(有向无环图)使其保证一个特定的顺序。更多细节你可以查阅Solidity 的官方文档。

在 Remix 上验证

  • 合约简单继承示例, 可以观察到 Baba 合约多了 Yeye 的函数image.pngimage.png
  • 合约多重继承可以参考简单继承的操作步骤来增加部署 Erzi 合约,然后观察暴露的函数以及尝试调用来查看日志
  • 修饰器继承示例image.pngimage.pngimage.png
  • 构造函数继承示例image.pngimage.png
  • 调用父合约示例image.pngimage.png
  • 菱形继承示例image.png

总结

这一讲,我们介绍了solidity继承的基本用法,包括简单继承,多重继承,修饰器和构造函数的继承、调用父合约中的函数,以及多重继承中的菱形继承问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/999434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新手必看!Python爬虫 教程:IP池的使用

前言 嗨喽~大家好呀,这里是小曼呐 ❤ ~! 一、简介 爬虫中为什么需要使用代理 一些网站会有相应的反爬虫措施,例如很多网站会检测某一段时间某个IP的访问次数,如果访问频率太快以至于看起来不像正常访客,它可能就会禁止这个IP的访…

CE单相智能电力仪表ADL200

安科瑞 华楠 ADL200 单相电子式电能表主要用于计量低压网络的单相有功电能,同时可测量电压、电流、功率等电量, 并可选配 RS485 通讯功能,方便用户进行用电监测、集抄和管理。可灵活安装于配电箱内,实现对不同区域和不 同 负 荷 …

分布式系统第三讲:全局唯一ID实现方案

分布式系统第三讲:全局唯一ID实现方案 本文主要介绍常见的分布式ID生成方式,大致分类的话可以分为两类:一种是类DB型的,根据设置不同起始值和步长来实现趋势递增,需要考虑服务的容错性和可用性; 另一种是类snowflake型…

信息化发展34

IT 审计目的 1 、IT 审计的目的是指通过开展IT 审计工作, 了解组织IT 系统与IT 活动的总体状况, 对组织是否实现口目标进行审查和评价, 充分识别与评估相关口风险,提出评价意见及改进建议, 促进组织实现IT 目标。 2 、…

禁用或卸载没那么复杂!如何在Windows 11上禁用或删除McAfee

​当你从Microsoft以外的制造商处购买新的Windows设备时,该设备可能已安装McAfee防病毒软件。虽然在你的电脑上安装防病毒软件总是一个好主意,但你可能更喜欢与McAfee不同的程序。在这种情况下,了解如何卸载McAfee是很重要的。 另一方面,你可能对McAfee很满意,但需要暂时…

忽悠苹果,销量垫底?小屏iPhone已经落寞,iPhone13mini即将停产

苹果公司的小屏iPhone系列可能即将走到尽头。据彭博社报道,苹果最新发布的 iPhone 13 mini 库存已经见底,部分款式在美国官网发货时间显示为2-3周,甚至最久达到了6-8周。这种现象表明,在周二的发布活动结束后,苹果最后…

SpringBoot底层注解

文章目录 前言一、Configuration二、Import导入组件三、Conditional条件装配四、ImportResource导入Spring配置文件五、ConfigurationProperties配置绑定总结 前言 本文主要讲诉Configuration、Import、Conditional、ImportResource、ConfigurationProperties注解。 先将实体…

一心堂正式启动“心链-SRM”项目,携手企企通搭建引领发展的采购供应链协同平台

近日,中国药品连锁零售行业首家上市企业一心堂药业集团股份有限公司(以下简称“一心堂”)与企企通成功召开“心链-SRM”采购供应链管理项目启动会。双方高层领导及项目团队关键成员出席现场,各子公司管理团队通过视频会议形式参与…

双碳目标下基于“遥感+”集成技术的碳储量、碳排放、碳循环、温室气体等多领域监测与模拟实践

卫星遥感具有客观、连续、稳定、大范围、重复观测的优点,已成为监测全球碳盘查不可或缺的技术手段,卫星遥感也正在成为新一代 、国际认可的全球碳核查方法。目的就是梳理碳中和与碳达峰对卫星遥感的现实需求,系统总结遥感技术在生态系统碳储量…

利用VB宏设置将多个excel表合并为一个

多个excel合并成一个excel文件-应用哥科技 Sub MergeExcelFiles() 声明变量 Dim MyFile As Variant Dim MySheet As Worksheet, MySheet1 As Worksheet Dim LastRow As Long, LastRow1 As Long Dim NextRow As Long 设置初始值 NextRow 1 打开多个Excel文件 MyFile Applicati…

【算法】分治法的应用——快速排序

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ …

30岁+文转码程序媛求职路复盘:也算是逆袭了!

这篇文章来自一位群友的分享&#xff1a; 这篇文章写于下班路上&#xff0c;刚刚入职不久&#xff0c;我想再冲刺一下大厂&#xff0c;阳哥建议我坚持总结打卡&#xff0c;可以尝试写写博客。 那我就从这篇开始吧&#xff0c;希望开个好头&#xff01; 上班的感觉真好 今天是…

bim与数字孪生智能建造的关系

随着建筑业数字化改革的推进&#xff0c;我们正迈入数字孪生时代&#xff0c;而真正实现建筑物数字孪生的智能建造&#xff0c;其基础前提是建造对象和建造过程的高度数字化&#xff0c;这样一个过程唯有依托BIM建立数据模型才能实现&#xff0c;真正达到智能建造或智慧运维。 …

内网穿透的应用-如何搭建WordPress博客网站,并且发布至公网上?

文章目录 如何搭建WordPress博客网站&#xff0c;并且发布至公网上&#xff1f;概述前置准备1 安装数据库管理工具1.1 安装图形图数据库管理工具&#xff0c;SQL_Front 2 创建一个新数据库2.1 创建数据库2.2 为数据库创建一个用户 3 安装PHP7.44. 创建一个新站点4.1 创建站点根…

CUDA小白 - NPP(6) 图像处理 Geometry Transforms (1)

cuda小白 原始API链接 NPP GPU架构近些年也有不少的变化&#xff0c;具体的可以参考别的博主的介绍&#xff0c;都比较详细。还有一些cuda中的专有名词的含义&#xff0c;可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus&#xf…

Win11自带微软输入法怎么输入π及其他希腊字母

如果用搜狗等第三方输入法的话就没有这些问题了&#xff0c;各种符号很方便。 自带的输入法输入 pi 和 pai 都不能正常输入 π \pi π 参考文章 https://www.cnblogs.com/qq-757617012/p/14078133.html 如果用自带的输入法可以采用以下方式 输入uuxl xl表示“希腊”&#x…

最长回文子串(Longest Palindromic substring)

什么叫回文串 就是正读和反读都是一样的字符串&#xff0c;比如aba,abba,cdc像这样的字符串都是回文字符串 暴力破解法来查找最长的回文子串 这个图解的意思就是我们要拿到每一个右边的数&#xff0c;然后与左边的数一一匹配 下面看一下java的实现代码 package com.pxx;/*** …

详细解析如何用“双指针“解题(面试必备,小白一看就会系类)

一、前言 大家在平时的训练和交流中肯定多少都会听过或者见过用"双指针"去快速的解题&#xff0c;那么大家有没有想过&#xff0c;为什么要用"双指针"呢&#xff1f;这里的"双指针"和我们平时了解的指针一样吗&#xff1f; 其实&#xff0c;这里…

Python数据分析实战-表连接-merge四种连接方式用法(附源码和实现效果)

实现功能 表连接-merge四种连接方式用法&#xff0c; 将两个pandas表根据一个或者多个键&#xff08;列&#xff09;值进行连接。 实现代码 import pandas as pddf1 pd.DataFrame({key: [a, b, d],data1: range(3)}) print(df1)df2 pd.DataFrame({key: [a, b, c, a, b],dat…

电商商品的前后台类目设计思路,小本本记下来(提供获取京东淘宝商品类目信息API 免费测试)

今天&#xff0c;我们来聊聊商品类目的设计思路。 商品是电商的根基&#xff0c;核心目标是销&#xff0c;也就是卖货。卖货可以多层理解&#xff0c;卖给谁&#xff0c;怎么卖&#xff0c;什么货&#xff0c;其实就是人货场的概念。 我理解的货&#xff0c;不仅是商品层面&a…