Solidity极简入门#13. 继承

这篇具有很好参考价值的文章主要介绍了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,不然就会报错。

  1. 如果某一个函数在多个继承的合约里都存在,比如例子中的hip()和pop(),在子合约里必须重写,不然会报错。

  1. 重写在多个父合约中都重名的函数时,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”,并且还分别从Yeye和Baba合约继承了yeye()和baba()两个函数。

修饰器的继承

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

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)

  1. 在子合约的构造函数中声明构造函数的参数,例如:

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,再写Adam和Eve两个合约继承God合约,最后让创建合约people继承自Adam和Eve,每个合约都有foo和bar两个函数。

// 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()会依次调用Eve、Adam,最后是God合约。

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

在Remix上验证

  • 合约简单继承示例, 可以观察到Baba合约多了Yeye的函数

solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
  • 合约多重继承可以参考简单继承的操作步骤来增加部署Erzi合约,然后观察暴露的函数以及尝试调用来查看日志

  • 修饰器继承示例

solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
  • 构造函数继承示例

solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
  • 调用父合约示例

solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档
  • 菱形继承示例

solidity继承,Solidity极简入门,区块链,智能合约,Powered by 金山文档

总结

这一讲,我们介绍了solidity继承的基本用法,包括简单继承,多重继承,修饰器和构造函数的继承、调用父合约中的函数,以及多重继承中的菱形继承问题。文章来源地址https://www.toymoban.com/news/detail-648855.html

到了这里,关于Solidity极简入门#13. 继承的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【区块链-智能合约工程师】第三篇:Solidity进阶(一)

    学习资料地址:WTF学院 库合约一般都是一些好用的函数合集(库函数),为了提升solidity代码的复用性和减少gas而存在。他和普通合约主要有以下几点不同: 不能存在状态变量 不能够继承或被继承 不能接收以太币 不可以被销毁 String库 String库合约是将uint256(大正整数)类型

    2024年02月06日
    浏览(13)
  • 区块链智能合约solidity的中的一些关键字

    区块链智能合约solidity的中的一些关键字

    目  录 pragma mapping msg对象 block对象 contract constructor struct 数据地址 地址类型 address payable revert 以下场景使用 revert() : require 以下场景使用 require() : assert 以下场景使用 assert(): 访问权限 internal public private external function returns return view pure constant event emit modifier pragma   

    2024年01月16日
    浏览(10)
  • Solidity 智能合约入门

    将一个数据放置在链上 我们对代码进行逐行分析,首先第一行 第一行表明此段代码是被GPL-3.0所授权。默认情况下,在发布源代码时加入机器可读许可证说明是很重要的。 GPL(GNU General Public License Versions) GPL协议一般还可以分为GPL2.0和GPL3.0两种,而GPL3.0是更新一代的开源标准

    2024年02月02日
    浏览(13)
  • 区块链web3智能合约Solidity学习资源整理

    Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。这门语言受到了 C++,Python 和 Javascript 语言的影响,设计的目的是能在以太坊虚拟机(EVM)上运行。 Solidity中文官方文档: https://solidity-cn.readthedocs.io/zh/develop/ https://learnblockchain.cn/docs/solidity/index.html 在线rem

    2024年03月19日
    浏览(17)
  • Solidity入门:我的第一段智能合约

    以太坊是一个全球性的、去中心化的金融和新型应用程序平台。在以太坊,我们可以通过智能合约代码来控制资产,并建立世界上任何地方皆可访问的应用程序。今天我们自己动手来写一段简单的智能合约代码,探索一下智能合约的奥秘。 【智能合约】 智能合约(英语:S

    2024年01月16日
    浏览(12)
  • 以太坊智能合约开发:Solidity 语言快速入门

    以太坊智能合约开发:Solidity 语言快速入门

    在本文中,我们从一个简单的智能合约样例出发,通过对智能合约源文件结构的剖析与介绍,使大家对Solidity语言有一个初步的认识。最后,我们将该智能合约样例在 Remix 合约编译器中编译、部署,观察其执行结果。 在开始之前,我们先对Solidity有个初步的了解,即Solidity是

    2023年04月09日
    浏览(16)
  • 《NFT区块链进阶指南二》Etherscan验证Solidity智能合约(Remix插件验证)

    《NFT区块链进阶指南二》Etherscan验证Solidity智能合约(Remix插件验证)

    前置参考文档:https://blog.csdn.net/sinat_34104446/article/details/130557703 合约验证是上传合约源代码到etherscan过程,在智能合约项目中,通常都是提供源码验证,增加项目信任度 验证合约后可以直接在etherscan上执行获取和设置方法,方便日常的管理员维护 以下使用remix进行验证并使用

    2024年02月05日
    浏览(11)
  • 【区块链技术开发】 Solidity使用Truffle Box工具实现预构建模板、自动化部署、创建智能合约示例代码

    专栏:区块链技术开发 Truffle Box是一个开发工具,为Truffle生态系统中的开发人员提供了预构建

    2023年04月16日
    浏览(81)
  • Solidity 小白教程:13. 继承

    Solidity 小白教程:13. 继承

    这一讲,我们介绍 solidity 中的继承( inheritance ),包括简单继承,多重继承,以及修饰器( modifier )和构造函数( constructor )的继承。 继承是面向对象编程很重要的组成部分,可以显著减少重复代码。如果把合约看作是对象的话, solidity 也是面向对象的编程,也支持继承

    2024年02月09日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包