solidity中的继承

1.继承

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

规则

  1. virtual: 父合约中的函数,如果希望子合约重写,需要加上virtual关键字。
  2. override:子合约重写了父合约中的函数,需要加上override关键。
// SPDX-License-Identifier: MIT
// 指定了许可证类型,MIT许可证,这是一种常用的开源许可证。pragma solidity ^0.8.22;
// 指定了Solidity编译器的版本范围,^表示与0.8.22版本兼容的最新版本。contract Yeye{event Log(string msg);function hip() public virtual{emit Log("Yeye");}function pop() public virtual{emit Log("Yeye");}function yeye() public virtual{emit Log("Yeye");}
}contract Baba is Yeye{function hip() public virtual override{emit Log("Baba");}function pop() public virtual override{emit Log("Baba");}function baba() public virtual {emit Log("Baba");}}

在这个例子中,Baba继承了Yeye,并且重写了hip()和pop()函数,同时添加了一个新的函数baba()。override关键字用于明确指出函数重写了父合约中的虚拟函数。

2.多重继承

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() public virtual override(Yeye,Baba){emit Log("Erzi");}function pop() public virtual override(Yeye,Baba){emit Log("Erzi");}}

在这个例子中,Erzi继承了Yeye和Baba,并且必须重写hip()和pop()函数,因为这两个函数在Yeye和Baba中都存在。

3.砖石继承(菱形继承)

菱形继承 (钻石继承) 是多重继承的一种特殊情况。

  A/ \
B   C\ /D
contract A {function foo() public pure virtual returns (string memory) {return "A";}
}contract B is A {function foo() public pure virtual override returns (string memory) {return "B";}
}contract C is A {function foo() public pure virtual override returns (string memory) {return "C";}
}
// 根据继承顺序, B C 平级, 所以顺序随意contract D1 is B, C {function foo() public pure override(B, C) returns (string memory) {return "D1";}
}contract D2 is C, B {function foo() public pure override(C, B) returns (string memory) {return "D2";}
}

调用父合约的构造函数

// SPDX-License-Identifier: MIT
// 指定了许可证类型,MIT许可证,这是一种常用的开源许可证。pragma solidity ^0.8.22;
// 指定了Solidity编译器的版本范围,^表示与0.8.22版本兼容的最新版本。contract A{string public name;constructor(string memory _name){name=_name;}}contract B{uint public number;constructor(uint _number){number=_number;}}//方法1 在声明的继承的时候调用contract D is A("Hello"),B(42){}//方法2-在声明构造函数的时候调用contract C is A,B{constructor(string memory _name,uint _number) A(_name) B(_number){}}//方法1和2可混用contract E is A("Hello"), B{constructor(uint _number) B(_number) {}}

构造函数的调用顺序:先继承的父合约 → 后继承的父合约 → 当前合约

所以,demo 1 是 A → B → C、 demo 2 是 A → B → D、 demo 3 是 A → B → E

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

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

4.总结

讲解一下完整的使用方法:

// SPDX-License-Identifier: MIT
// 这是一个许可证标识符,用于指定代码的许可证类型。MIT许可证是一种宽松的自由软件许可证。pragma solidity ^0.8.26;
// 这行代码指定了Solidity编译器的版本。`^`符号表示与0.8.26版本兼容的最新版本。/* Inheritance tree
A / \
B C \/ D
*/
// 这是一个继承树的注释,说明了合约之间的继承关系。A是基类,B和C继承自A,D继承自B和C。contract A {// 定义了一个名为A的合约。// 这是一个事件。你可以在函数中触发事件,并将它们记录在交易日志中。// 在我们的例子中,这将有助于追踪函数调用。event Log(string message);// 事件Log被定义,它接受一个字符串参数message。function foo() public virtual {emit Log("A.foo called");}// 函数foo被定义为public,并且被标记为virtual,这意味着它可以被重写。// 当foo被调用时,它触发了事件Log,并传递了字符串"A.foo called"。function bar() public virtual {emit Log("A.bar called");}// 函数bar也被定义为public和virtual,当bar被调用时,它触发了事件Log,并传递了字符串"A.bar called"。
}contract B is A {// 定义了一个名为B的合约,它继承自合约A。function foo() public virtual override {emit Log("B.foo called");A.foo();}// 函数foo在B中被重写。它触发了事件Log,表示"B.foo called",然后调用了父合约A中的foo函数。function bar() public virtual override {emit Log("B.bar called");super.bar();}// 函数bar在B中被重写。它触发了事件Log,表示"B.bar called",然后使用super关键字调用了父合约A中的bar函数。
}contract C is A {// 定义了一个名为C的合约,它继承自合约A。function foo() public virtual override {emit Log("C.foo called");A.foo();}// 函数foo在C中被重写。它触发了事件Log,表示"C.foo called",然后调用了父合约A中的foo函数。function bar() public virtual override {emit Log("C.bar called");super.bar();}// 函数bar在C中被重写。它触发了事件Log,表示"C.bar called",然后使用super关键字调用了父合约A中的bar函数。
}contract D is B, C {// 定义了一个名为D的合约,它同时继承自合约B和C。// Try:// - Call D.foo and check the transaction logs.//   Although D inherits A, B and C, it only called C and then A.// - Call D.bar and check the transaction logs//   D called C, then B, and finally A.//   Although super was called twice (by B and C) it only called A once.function foo() public override(B, C) {super.foo();}// 函数foo在D中被重写。它使用super关键字调用了父合约中的foo函数。// 由于D继承自B和C,而B和C都重写了foo函数,这里的super.foo()将调用C中的foo函数,然后C中的foo会调用A中的foo。function bar() public override(B, C) {super.bar();}// 函数bar在D中被重写。它使用super关键字调用了父合约中的bar函数。// 由于D继承自B和C,而B和C都重写了bar函数,这里的super.bar()将首先调用C中的bar函数,然后C中的bar会调用B中的bar,最后B中的bar会调用A中的bar。
}

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

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

相关文章

还不会使用MySQL的复合查询?一篇文章快速教会你

使用逻辑运算符 AND 用于同时满足多个条件。OR 用于满足任一条件 SELECT * FROM employees WHERE department Sales AND salary > 50000;从 employees 表中选取所有在 “Sales” 部门工作且薪水高于50,000的员工记录。 子查询 子查询是在一个 SELECT 语句中嵌套另一个 …

AppInventor2能否用网络摄像头画面作为屏幕的背景?

// 视频是否可以作为背景? // 有会员提问:能否用网络摄像头的实时画面作为屏幕的背景?就跟这个一样背景全覆盖: 摄像头画面是一个在线的网站链接视频流。 // 原先思路 // 1、目前原生组件无法直接实现这个功能,屏幕…

显示器接口

不同的显示输出接口支持的分辨率和刷新率各有差异,以下是一些常见接口的概述: 1. HDMI (High-Definition Multimedia Interface) 版本 1.4:支持最大分辨率 4K (3840x2160) 30Hz,1080p 120Hz。版本 2.0:支持最大分辨…

国产操作系统卖疯了!最营收7.84亿,最低1.5亿

最近看各种报道,似乎国产化有提速的绩效,那么既然如此,各个国产操作系统厂商是不是都起飞了呢? 周末闲暇之余,我们来看看各家的营收表现。 银河麒麟2024年1-9月一共卖了多少钱? 前几天中国软件发布了202…

django请求与响应

目录 一、请求Request 利用HTTP协议向服务器传参有几种途径 Django中的QueryDict对象 1> GET属性获取查询字符串Query String 参数 2> POST属性 获取请求体参数 3> META属性 获取请求头数据 4> 其他常用HttpRequest对象属性 二、响应Response 1> HttpR…

深度学习:抑制过拟合

过拟合问题 1.过拟合:当模型在训练数据上表现很好,但在未见过的测试数据上表现较差时,我们称之为过拟合。过拟合通常发生在模型过于复杂,参数过多,或者训练数据量不足的情况下。 2.权重过大:在过拟合的情况…

Python venv创建失败问题

在Ubuntu中,笔者需要创建虚拟环境时失败: python3.11 -m venv env 报错信息如下:Error: Command [****/env/bin/python3.11, -m, ensurepip, --upgrade, --default-pip] returned non-zero exit status 1. 尝试执行一下看看是什么错误: python3.11 -m ensurepip …

CDN加速实战:使用七牛云CDN加速阿里云OSS资源访问

今天是双11搞活动,在阿里云1元注册了个域名,想着在学CDN,想使用CDN做个加速项目,但是阿里的要收费,上网查了下七牛云的不收费,想着将七牛云的CDN结合阿里的DNS做个访问加速,刚好看到了阿里的一个文章,照着改了改,实践成功了。 阿里文章:使用CDN加速OSS资源访问_对象…

Git本地分支更新推送到远程主分支上

本地分支(debug)开发之前: git pull origin dev(主分支)git merge 这步merge可能会现异常:error:Merging is not possible because you have ynmerged files,出现冲突文件&#xff…

嵌入式学习——IIC协议

IIC(Inter-Integrated Circuit)是一种串行通信协议,由飞利浦公司于1980年代提出。它允许多个从设备通过两条线(SDA和SCL)与一个或多个主设备进行通信。IIC协议是多主、多从的,适合在短距离内的设备间通信。…

Mongodb使用视图连接两个集合

您可以使用 $lookup 为两个集合创建一个视图,然后对该视图运行查询。应用程序可以查询视图,而无需构建或维护复杂的管道。 例子 创建两个样本集合 inventory 和 orders: db.inventory.insertMany( [{ prodId: 100, price: 20, quantity: 1…

spring的自定义注解

在 Spring 中,自定义注解可以帮助我们实现自定义的功能,比如切面逻辑、权限控制、数据校验等。自定义注解通常结合 Spring 的 AOP 或其他功能使用,以增强业务逻辑。下面是创建自定义注解的一般步骤,以及使用示例。 一、创建自定义…

qt QStatusBar详解

1、概述 QStatusBar是Qt框架提供的一个小部件,用于在应用程序窗口底部显示状态信息。它可以显示一些固定的文本和图标,并且可以通过API动态更新显示内容。QStatusBar通常是一个水平的窗口部件,能够显示多行文本内容,非常适合用于…

大型语言模型的运行成本分析

大型语言模型 (LLM) 一直处于生成式 AI 革命的前沿,尤其是自 ChatGPT 出现以来。然而,它们的全部潜力尚未得到释放,而一个重大障碍是成本。将 LLM 纳入应用程序的费用范围从按需用例的几美分到在云环境中托管单个 LLM 实例的每月 20,000 美元…

Spring Boot接收参数的19种方式

Spring Boot是一个强大的框架,允许开发人员通过多种方式接收和处理参数。无论是HTTP请求参数、路径变量,还是请求体中的数据,Spring Boot都能提供灵活的处理方式。本文将介绍19种不同的方式来接收参数。 1. 查询参数(Query Param…

Matlab高光谱遥感

原文链接:Matlab高光谱遥感https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247623643&idx5&sne4557ed43728f851140b100f42286988&chksmfa8da23ccdfa2b2a4d795bf4087f672faaa7082d1f52e046616ab7bf196a6eef89ea553d06b1&token1392391660&…

OPENAI官方prompt文档解析

官方文档地址:https://platform.openai.com/docs/guides/gpt-best-practices 文档中文版来源:OpenAI 官方提示工程指南 [译] | 宝玉的分享 (baoyu.io) 1.写清楚说明 如果prompt给的范围十分模糊或是过于宽泛,那么GPT就会开始猜测您想要的内容,从而导致生成的结果偏离预期. …

C++游戏开发

C游戏开发概述 C 是游戏开发中的主要编程语言之一,因其性能、控制和广泛的生态系统而受到开发者的青睐。随着游戏行业的迅速发展,C 被用来构建许多成功的游戏和游戏引擎。本文将深入探讨 C 在游戏开发中的应用,包括基础概念、技术栈、示例代…

共模噪声和差模噪声

电源芯片加上负载和不加负载输出的纹波不一样,不加负载的情况下纹波比较小。 可以测量出DCDC电源的输出电压纹波为100Khz,刚好对应电源芯片的开关频率。可以看到纹波上面有一部分的小噪声,放大后用示波器观察频率为几Mhz。 对付上面的频率比…

DevOps赋能:优化业务价值流的实战策略与路径(上)

上篇:价值流引领与可视化体系构建 一、前言 在快速迭代的软件项目和产品开发生态中,我们始终围绕两个核心目标:一是确保每一项工作都能为客户创造实际价值,这是产品团队的核心使命;二是确保这些有价值的工作能够高效…