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合约同时继承了Base1和Base2。由于Base1和Base2都定义了一个hello函数,因此Derived合约需要明确地重写这个函数,并通过override(Base1, Base2)指明它覆盖了来自Base1和Base2的hello函数。
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中的访问修饰符(public、private、internal、external)在继承中也有重要作用。例如:
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合约继承了Base1和Base2,并且在构造时按照继承顺序调用了Base1和Base2的构造函数。
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合约继承了Base1和Base2,构造函数的调用顺序是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还支持多重继承、构造函数的继承、状态变量的访问、事件的继承以及修饰符的继承。开发者可以利用这些特性构建复杂且高效的智能合约系统。
相关文章:
solidity高阶 -- 继承
Solidity是一种面向区块链的智能合约编程语言,广泛应用于以太坊等区块链平台。继承是Solidity中一个非常重要的特性,它允许开发者通过创建子合约来扩展父合约的功能,从而实现代码的复用和层次化设计。本文将通过具体实例详细介绍Solidity语言…...
SpringBoot统一数据返回格式 统一异常处理
统一数据返回格式 & 统一异常处理 1. 统一数据返回格式1.1 快速入门1.2 存在问题1.3 案列代码修改1.4 优点 2. 统一异常处理 1. 统一数据返回格式 强制登录案例中,我们共做了两部分⼯作 通过Session来判断⽤⼾是否登录对后端返回数据进⾏封装,告知前端处理的结果 回顾 后…...
C语言学习强化
前言 数据的逻辑结构包括: 常见数据结构: 线性结构:数组、链表、队列、栈 树形结构:树、堆 图形结构:图 一、链表 链表是物理位置不连续,逻辑位置连续 链表的特点: 1.链表没有固定的长度…...
反馈驱动、上下文学习、多语言检索增强等 | Big Model Weekly 第55期
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 01 A Bayesian Approach to Harnessing the Power of LLMs in Authorship Attribution 传统方法严重依赖手动特征,无法捕捉长距离相关性,限制了其有效性。最近的研究利用预训练语言模型的…...
Redis 详解
简介 Redis 的全称是 Remote Dictionary Server,它是一个基于内存的 NoSQL(非关系型)数据库,数据以 键值对 存储,支持各种复杂的数据结构 为什么会出现 Redis? Redis 的出现是为了弥补传统数据库在高性能…...
git reset (取消暂存,保留工作区修改)
出现这种情况的背景:我不小心把node_modules文件添加到暂存区了,由于文件过大,导致不能提交,所以我想恢复之前的状态,但又不想把修改的代码恢复为之前的状态,所以使用这个命令可以只恢复暂存区的状态&#…...
C++ 自定义字面量
在C11中,用户自定义字面量(User-Defined Literals)为程序员提供了前所未有的灵活性和便利性,它允许我们根据自己的需求定义字面量,从而使代码更加直观、易读且富有表现力。 什么是用户定义字面量? 在C中&…...
2024年面对不确定性
24年处在了十字路口,面对工作、家庭、生活的责任,一切变得不确定了,量子力学给了我们新的认识世界的角度,不确定性才是这个世界的底色,我们怎么选择? 不停的思考 霍金在大设计书中给出了深刻的哲学思想&a…...
Coze插件开发之基于已有服务创建并上架到扣子商店
Coze插件开发之基于已有服务创建并上架到扣子商店 在应用开发中,需要调用各种插件,以快速进行开发。但有时需要调用的插件在扣子商店里没有,那怎么办呢? 今天就来带大家快速基于已有服务创建一个新的插件 简单来讲,就是…...
Oracle 创建用户和表空间
Oracle 创建用户和表空间 使用sys 账户登录 建立临时表空间 --建立临时表空间 CREATE TEMPORARY TABLESPACE TEMP_POS --创建名为TEMP_POS的临时表空间 TEMPFILE /oracle/oradata/POS/TEMP_POS.DBF -- 临时文件 SIZE 50M -- 其初始大小为50M AUTOEXTEND ON -- 支持…...
企业微信开发009_使用WxJava企业微信开发框架_封装第三方应用企业微信开发002_并且实现多企业授权访问---企业微信开发011
继续接上一节来贴代码: 接下来看 config部分的代码,这部分代码,系统启动的时候,就会执行,从而把配置的一些,配置读取出来,创建,针对每个企业微信的,操作service. 首先看yml配置文件中配置部分: 可以先看一下demo中: 提供了一个配置的示例,当然这个是针对 企业内部自建应用 …...
机器学习 - 初学者需要弄懂的一些线性代数的概念
一、单位矩阵 在数学中,单位矩阵是一个方阵,其主对角线上的元素全为1,其余元素全为0。单位矩阵在矩阵乘法中起到类似于数字1在数值乘法中的作用,即任何矩阵与单位矩阵相乘,结果仍为原矩阵本身。 单位矩阵的定义&…...
【学术会议-第五届机械设计与仿真国际学术会议(MDS 2025) 】前端开发:技术与艺术的完美融合
重要信息 大会官网:www.icmds.net 大会时间:2025年02月28日-03月02日 大会地点:中国-大连 会议简介 2025年第五届机械设计与仿真国际学术会议(MDS 2025) 将于2025年02月28-3月02日在中国大连召开。MDS 2025将围绕“机械设计”…...
RabbitMQ 分布式高可用
文章目录 前言一、持久化与内存管理1、持久化机制2、内存控制1、命令行2、配置文件 3、内存换页4、磁盘控制 二、集群1、Erlang的分布式特性2、RabbitMQ的节点类型2.1、磁盘节点 (Disk Node)2.2、内存节点 (RAM Node) 3、构建集群3.1 普通集群3.2 镜像队列3.3、高可用实现方案3…...
海康工业相机 SDK对接 Hikvision
有C#基础的,可以参考下,直接上代码 BaseResult 来自于Nuget包,搜Rotion可以搜出来 LS.Standard.Data 海康的接口操作,要先引用相应的dll using MvCamCtrl.NET; using PCZD.Commons.Data.CameraModel; using PCZD.Data; using Sys…...
开发技巧,vue 中的动态组件的引用 component + is
在项目中很多时候有切换 tab 的场景,一般来说都是用 v-if 或者 v-show 然后根据各种条件来控制显示隐藏。 其实我们可以使用 vue 中的动态组件,也能实现这个效果 <!-- currentTab 改变时组件也改变 --> <component :is"currentTab"…...
MySQL 二进制安装(正式篇)
Author:Arsen Date:2025/01/24 官方参考文档:点击链接跳转 目录 规划下载安装管理FAQ 规划 OSMySQL Server Version备注CentOS 7.9 or Linux - Generic8.0.33(GNU libc) 2.17 下载 二进制包下载地址:https://downloads.mysql.…...
MongoDB 数据库备份和恢复全攻略
在当今数据驱动的时代,数据库的稳定运行和数据安全至关重要。MongoDB 作为一款流行的 NoSQL 数据库,以其灵活的文档模型和高扩展性备受青睐。然而,无论数据库多么强大,数据丢失的风险始终存在,因此掌握 MongoDB 的备份…...
K8S部署DevOps自动化运维平台
持续集成(CI) 持续集成强调开发人员提交了新代码之后,立刻自动的进行构建、(单元)测试。根据测试结果,我 们可以确定新代码和原有代码能否正确地集成在一起。持续集成过程中很重视自动化测试验证结果&#…...
工业相机 SDK 二次开发-Sherlock插件
本文介绍了 sherlock 连接相机时的插件使用。通过本套插件可连接海康的工业相机。 一.环境配置 1. 拷贝动态库 在用户安装 MVS 目录下按照如下路径 Development\ThirdPartyPlatformAdapter 找到目 录为 DalsaSherlock 的文件夹,根据 Sherlock 版本找到…...
分布式版本控制系统:Git
1 Git概述 Git官网:https://git-scm.com/ Git是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目Git易于学习,占地面积小,性能极快。它具有廉价的本地库、方便的暂存区域和多个工作流分支等特性…...
页高速缓存与缓冲区缓存的应用差异
页高速缓存(Page Cache)与缓冲区缓存(Buffer Cache)是计算机系统中用于提高数据访问性能的两种不同类型的缓存机制,它们的差异主要体现在以下几个方面: 缓存目的 页高速缓存:主要用于加速对磁…...
C语言编程笔记:文件处理的艺术
大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文一、为什么要用文件二、文件的分…...
如何编写一个MyBatis插件?
大家好,我是锋哥。今天分享关于【Redis为什么这么快?】面试题。希望对大家有帮助; 如何编写一个MyBatis插件? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 编写 MyBatis 插件需要使用 MyBatis 提供的插件接口,MyBa…...
验证二叉搜索树(力扣98)
根据二叉搜索树的特性,我们使用中序遍历,保证节点按从小到大的顺序遍历。既然要验证,就是看在中序遍历的条件下,各个节点的大小关系是否符合二叉搜索树的特性。双指针法和适合解决这个问题,一个指针指向当前节点&#…...
C语言初阶牛客网刷题—— HJ34 图片整理【难度:中等】
1. 题目描述 牛客网在线OJ链接 Lily上课时使用字母数字图片教小朋友们学习英语单词,每次都需要把这些图片按照大小(ASCII码值从小到大)排列收好。请大家给Lily帮忙,通过C语言解决。 输入描述:Lily使用的图片包括 “A…...
Golang Gin系列-7:认证和授权
在本章中,我们将探讨Gin框架中身份验证和授权的基本方面。这包括实现基本的和基于令牌的身份验证,使用基于角色的访问控制,应用中间件进行授权,以及使用HTTPS和漏洞防护保护应用程序。 实现身份认证 Basic 认证 Basic 认证是内置…...
mysql create table的用法
在MySQL中创建表的基本语法如下: CREATE TABLE table_name (column1 datatype,column2 datatype,column3 datatype,... );这里是一个例子,假设我们要创建一个名为employees的表,包含以下字段: id:一个整数类型的主键…...
蓝桥杯算法赛第25场月赛
前言 这些题对于我的难度有点大,大家感兴趣的可以来做一下,看一下,下面给大家展示一下题目 1. 桃花运走向【算法赛】 问题描述 2025 年春节,小明和小红兴致勃勃地去庙会玩耍。庙会上,一个算命先生摆摊算命…...
从介词到状语 (什么都研究一点系列)
契子 英语中介词的使用频率很高, 但在使用时本质上作为状语而成为句子成分, 没错 “本质上” 这三个字就是状语 😃 形式上是这样: 介词 -> 状语 -> 句子 常见的介词: 时间 at, 地点 on, 原因 of, 方式 in, 伴随 with, 比较 than, 条件 if 等等 下面我们开…...
