当前位置: 首页 > news >正文

Inheritance

本节是《Solidity by Example》的中文翻译与深入讲解,专为零基础或刚接触区块链开发的小白朋友打造。我们将通过“示例 + 解说 + 提示”的方式,带你逐步理解每一段 Solidity 代码的实际用途与背后的逻辑。

Solidity 是以太坊等智能合约平台使用的主要编程语言,就像写网页要用 HTML 和 JavaScript,写智能合约就需要会 Solidity。

如果你从没写过区块链代码也没关系,只要你了解一点点编程概念,比如“变量”“函数”“条件判断”,我们就能从最简单的例子开始,一步步建立你的 Solidity 编程思维。

Inheritance

继承
Solidity 支持多重继承。合约可以通过 is 关键字继承其他合约。

将被子合约覆盖的函数必须声明为 virtual

覆盖父合约函数的函数必须使用 override 关键字。

继承顺序很重要。

必须按照从“最基础”到“最衍生”的顺序列出父合约。

什么是 Solidity 继承?

在 Solidity 中,继承允许一个合约(子合约)获取另一个合约(父合约)的功能(如函数、状态变量),通过 is 关键字实现。

  • 比喻:继承像连锁餐厅的分店(子合约)继承总店(父合约)的品牌、菜单和运营规则,同时可以自定义部分内容(如菜单项)。
  • 支持多重继承,一个子合约可继承多个父合约(如 D is B, C)。

关键字的作用

  • virtual:标记父合约的函数,允许子合约覆盖(重写)其逻辑。

    • 比喻:像总店规定“菜单可以调整”,允许分店自定义。
  • override:子合约中标记覆盖父合约的函数,确保明确修改。

    • 比喻:分店声明“我改了总店的菜单”。
  • 继承顺序:从“最基础”(如核心功能)到“最衍生”(如扩展功能),影响构造函数调用(参考历史对话中的构造函数)和函数搜索顺序。

    • 比喻:像连锁店先继承总部的核心规则(A),再添加区域特色(B, C)。
  • 多重继承的搜索规则

    • 当子合约调用父合约函数(如 super.foo())时,Solidity 按从右到左、深度优先的顺序搜索父合约。
    • 比喻:像分店需要一道菜的配方,先查最近的区域总部(右边父合约),再查总店。
// SPDX-License-Identifier: MIT
// 使用 MIT 许可证,允许自由使用、修改和分发代码。pragma solidity ^0.8.26;
// 指定 Solidity 编译器版本,必须为 0.8.26 或更高(但低于 0.9.0)。/* Graph of inheritanceA/ \B   C/ \ /
F  D,E
*/
// 继承关系图:
// - A 是基础合约(父合约)。
// - B 和 C 继承 A。
// - D 和 E 继承 B 和 C(多重继承)。
// - F 继承 A 和 B。
// 表示合约之间的层级关系,D 和 E 是多重继承的复杂案例。contract A {function foo() public pure virtual returns (string memory) {return "A";}// 定义基础合约 A。// 函数 foo:// - public:外部和内部可调用。// - pure:不读写区块链状态,仅返回字符串 "A"。// - virtual:允许子合约覆盖。// - returns (string memory):返回内存中的字符串。// 比喻:A 是总店,提供默认菜单项 "A"。
}// Contracts inherit other contracts by using the keyword 'is'.
// 合约通过 'is' 关键字继承其他合约。
contract B is A {// Override A.foo()// 覆盖 A 的 foo 函数function foo() public pure virtual override returns (string memory) {return "B";}// 定义合约 B,继承 A(通过 is A)。// 函数 foo:// - 覆盖 A 的 foo 函数(使用 override 关键字)。// - virtual:允许进一步的子合约(如 D、F)覆盖。// - 返回 "B"。// 比喻:B 是分店,改用自己的菜单项 "B"。
}contract C is A {// Override A.foo()// 覆盖 A 的 foo 函数function foo() public pure virtual override returns (string memory) {return "C";}// 定义合约 C,继承 A。// 函数 foo:// - 覆盖 A 的 foo 函数,返回 "C"。// - virtual:允许进一步覆盖。// 比喻:C 是另一家分店,菜单项改为 "C"。
}// Contracts can inherit from multiple parent contracts.
// When a function is called that is defined multiple times in
// different contracts, parent contracts are searched from
// right to left, and in a depth-first manner.
// 合约可以继承多个父合约。
// 当调用一个在多个父合约中定义的函数时,父合约按从右到左、深度优先的顺序搜索。contract D is B, C {// D.foo() returns "C"// since C is the right most parent contract with function foo()// D.foo() 返回 "C",因为 C 是最右边的父合约,包含 foo 函数。function foo() public pure override(B, C) returns (string memory) {return super.foo();}// 定义合约 D,继承 B 和 C(多重继承)。// 函数 foo:// - override(B, C):覆盖 B 和 C 的 foo 函数(需明确指定)。// - super.foo():调用父合约的 foo 函数。// - 搜索顺序:从右到左(C → B),C 是最右父合约,调用 C 的 foo,返回 "C"。// 比喻:D 是综合分店,查菜单时先看 C 的("C"),因为 C 在继承列表中更靠右。
}contract E is C, B {// E.foo() returns "B"// since B is the right most parent contract with function foo()// E.foo() 返回 "B",因为 B 是最右边的父合约,包含 foo 函数。function foo() public pure override(C, B) returns (string memory) {return super.foo();}// 定义合约 E,继承 C 和 B(顺序相反)。// 函数 foo:// - override(C, B):覆盖 C 和 B 的 foo 函数。// - super.foo():调用父合约的 foo 函数。// - 搜索顺序:从右到左(B → C),B 是最右父合约,调用 B 的 foo,返回 "B"。// 比喻:E 是另一家综合分店,查菜单时先看 B 的("B"),因为 B 在继承列表中更靠右。
}// Inheritance must be ordered from "most base-like" to "most derived".
// Swapping the order of A and B will throw a compilation error.
// 继承必须从“最基础”到“最衍生”排序。
// 交换 A 和 B 的顺序将导致编译错误。
contract F is A, B {function foo() public pure override(A, B) returns (string memory) {return super.foo();}// 定义合约 F,继承 A 和 B。// 继承顺序:A(基础)→ B(衍生,继承 A)。// 函数 foo:// - override(A, B):覆盖 A 和 B 的 foo 函数。// - super.foo():调用父合约的 foo 函数。// - 搜索顺序:从右到左(B → A),B 是最右父合约,调用 B 的 foo,返回 "B"。// 如果写成 is B, A(违反“基础到衍生”),编译报错,因为 B 依赖 A。// 比喻:F 是分店,先继承总店 A 的核心规则,再继承 B 的特色菜单。
}

代码包含六个合约,展示继承机制、多重继承、函数覆盖和搜索顺序:

  • 合约 A:基础合约,定义可被覆盖的 foo 函数(返回 "A")。
  • 合约 BC:继承 A,分别覆盖 foo 返回 "B""C"
  • 合约 DE:多重继承 BC,通过 super.foo() 展示父合约函数的搜索顺序(右到左)。
  • 合约 F:继承 AB,验证继承顺序规则(从基础到衍生)。

继承的本质

  • 继承允许子合约复用父合约的代码(函数、状态变量),并通过覆盖(override)自定义逻辑。
  • 比喻:
    • 父合约像连锁餐厅的总店,提供标准菜单(foo 返回 "A")。
    • 子合约像分店,继承总店菜单(is A),可自定义(B 返回 "B"C 返回 "C")。
    • 多重继承(D is B, C)像分店结合多家总部的特色,调用时按顺序选择(右到左)。
  • 核心功能:
    • 代码复用:子合约继承父合约的函数和状态变量,减少重复代码。
    • 函数覆盖:通过 virtualoverride 修改父合约逻辑。
    • 多重继承:支持继承多个父合约,函数调用按右到左、深度优先搜索。
    • 继承顺序:从“最基础”(如 A)到“最衍生”(如 B),确保依赖关系正确。

代码功能

  • 合约 A
    • 基础合约,定义 foo 函数(返回 "A"),标记为 virtual 允许覆盖。
    • 模拟总店的核心功能。
  • 合约 BC
    • 继承 A,覆盖 foo 分别返回 "B""C",仍标记 virtual 允许进一步覆盖。
    • 模拟分店的定制功能。
  • 合约 DE
    • 多重继承 BC,通过 super.foo() 调用父合约的 foo
    • D is B, C:调用 C.foo()(返回 "C",因 C 更靠右)。
    • E is C, B:调用 B.foo()(返回 "B",因 B 更靠右)。
    • 展示多重继承的搜索规则(右到左)。
  • 合约 F
    • 继承 AB,验证继承顺序(AB)和 super.foo()(返回 "B")。
    • 强调“基础到衍生”的顺序规则。

继承的注意事项

  • 继承顺序:
    • 必须从“最基础”到“最衍生”(如 A, BB 依赖 A)。
    • 错误顺序(如 B, A)导致编译错误,因依赖关系不满足。
  • 函数覆盖:
    • 父合约函数需标记 virtual,子合约覆盖需用 override
    • 多重继承需明确指定覆盖的父合约(如 override(B, C))。
    • super 调用按右到左、深度优先搜索,确保逻辑清晰。
  • Gas 成本:
    • 多重继承增加部署 Gas(因需初始化多个父合约)。
    • super 调用增加 Gas(因搜索父合约),尽量简化
http://www.dtcms.com/a/309506.html

相关文章:

  • 什么是链游
  • Java:高频面试知识分享2
  • vue+cesium+geoserver跨域问题
  • 计算机组成原理2-2:进位计数制及其数据之间的相互转换
  • ubuntu 镜像克隆
  • React + ts + react-webcam + CamSplitter 实现虚拟摄像头解决win摄像头独占的问题
  • Java 22 新特性解析与代码示例
  • leecode42 接雨水
  • Mysql join语句
  • ansible简单playbook剧本例子2
  • CMake set_source_files_properties使用解析
  • 如何通过黑白棋盘进行定位配准融合?(前后安装的两个相机)
  • 大模型微调实战 -基于SWIFT框架
  • 南太平洋金融基建革命:斐济-巴新交易所联盟的技术破局之路 ——从关税动荡到离岸红利,跨境科技如何重塑太平洋资本生态
  • 使用Gemini API开发领域智能聊天机器人的思路
  • js判断是个变量和属性是否是有效值
  • PixelCNN介绍:VQ-VAE的前一步探索
  • 2025年Python Web框架之争:Django、Flask还是FastAPI,谁将主宰未来?
  • JsHook入门
  • 什么是爬虫协议?
  • 如何优雅删除Docker镜像和容器(保姆级别)
  • 热能小车cad【12张】三维图+设计说明书
  • 机械学习中的一些优化算法(以逻辑回归实现案例来讲解)
  • 【Flutter3.8x】flutter从入门到实战基础教程(五):Material Icons图标的使用
  • 燃气营商环境测评:以用户反馈推动服务升级​(第三方市场调查)
  • 逻辑回归----银行贷款模型优化
  • 嵌入式教学的云端革命:高精度仿真如何重塑倒车雷达实验与工程教育——深圳航天科技创新研究院赋能新一代虚实融合实训平台
  • IIS 让asp.net core 项目一直运行
  • Linux文件系统理解2
  • OpenGL Camera