玩以太坊链上项目的必备技能(OOP-合约继承-Solidity之旅九)

news2025/1/13 8:04:59

继承

我们今天不讲别的,就只讲合约继承相关的内容。(您是不是感觉这话挺眼熟的,没错,您确实看过,前一篇开头便是今天我们不讲三国,来讲讲 流程控制,您会觉得我上头了还是怎么!)

闲话少叙,咱们尽快的切入正题。

有过面向对象编程思想(OOP)都知道,继承是比较重要的一环,也正是继承让代码复用,维护也变得简单了起来(当然咯,这只是相对而言,维护工作依旧还是那样!)。

我们知道c++支持多继承,而 Solidity 也是支持多继承的,毕竟是受了它的影响嘛!从事Java的朋友这时可能最想说的是,什么啊,Java 设计者当初就是为了避免多继承所带来的问题,而决定摒弃多继承的。

虽然说多继承会破坏面向对象思想(OOP),但诸如表面上只支持单继承的 PHP,在 PHP 5.4 却引入了triat新特性,弥补了在 PHP 中单继承的不足。

在 Solidity 声明继承关系还是很容易的,使用关键字is,例如: contract Bird is Animal {}

创建合约时, 合约的 构造函数 (一个用关键字 constructor 声明的函数)会执行一次。 构造函数是可选的。只允许有一个构造函数,这意味着不支持重载

构造函数执行完毕后,合约的最终代码将部署到区块链上。此代码包括所有公共和外部函数以及所有可以通过函数调用访问的函数。 部署的代码没有 包括构造函数代码或构造函数调用的内部函数。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

//base contract
contract Animal  {
   //前面我们讲过 只要将 状态变量声明为 public,
   //solidity自动会为我们生成一个与状态变量名相同的public 函数
   string public name = " base Animal";
}

//contract Bird 继承了 contract Animal
contract Bird is Animal {
   //构造器 初始化相关数据
   constructor() {
      name = "bage Bird";
   }

   function getName() public view returns (string memory) {
        return name;
    }
  
}

在这里插入图片描述

重载(Override)

刚刚我们在说到构造器的时候,有提到重载,对于有过面向对象思想的您,想必是再清楚不过重载的概念了。

而在 Solidity 实现重载这一功能也是有相应的约束的。

  • virtual: 父合约中的函数,如果希望子合约重写,需要加上virtual关键字。
  • override:子合约重写了父合约中的函数,需要加上override关键字。
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

//base contract
contract Animal  {
   function eat() public  virtual  returns(string memory){
      return "animal eat";
   }
}

//contract Bird 继承了 contract Animal
contract Bird is Animal {
   
   function eat() public pure override returns(string memory) {
      return "bird eat";
   }
  
}

在这里插入图片描述

多重继承

展现技术的时刻到了,我们一上来就说 Solidity 支持多继承,可你展示了这么多,也没见任何的多继承的内容啊!

毕竟,先讲清了单继承多继承也就那么回事了!

作为聪明睿智的您想必会问,多重继承,那么怎么保证到底是哪个被继承合约先执行呢?

您看,您这个问题,问的就比较有深度了,是的,所以在 Solidity 的多重继承是依次排序下来的。

例如:有一个合约 A,若继承 合约 B 和 合约 C,那么应该写成contract A is B,C {},若合约 B 和合约 C 顺序颠倒了,那么最后执行的结果也是不一样的。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

//base contract
contract Animal  {
   function eat() public  virtual  returns(string memory){
      return "animal eat";
   }
}

contract Flyer {
   function fly() public virtual returns (string memory){
      return " fly...";
   }
}

//contract Bird 继承了 contract Animal
contract Bird is Animal,Flyer {
   
   function eat() public pure override returns(string memory) {
      return "bird eat";
   }

   function fly() public pure override returns (string memory){
      return " bird fly...";
   }
  
}

在这里插入图片描述

基类构造函数的参数

对于基合约构造函数有参数的情况,派生合约需要指定所有参数,对于派生合约有两种方式。

  • 1、派生合约在继承列表中调用基合约的构造函数。如contract Bird is Animal("bage") {}
  • 2、在派生合约的构造函数进行指定。如:contract Bird is Animal { constructor() Animal("bage" ) { } }
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

//base contract
contract Animal  {
   string name;

   constructor(string memory _name){
      name = _name;
   }
}

//第一种:派生合约继承基合约 直接在继承列表中给基类构造函数传参
contract Bird is Animal("bage") {
   //其实这个写不写都没事,不写,编译器自动默认的就是这个
   constructor() {}
}

contract Dog is Animal{
   //第二种则在派生合约的构造函数对基合约构造函数进行传参
   constructor() Animal("diba"){

   }
}

在这里插入图片描述

如果构造函数参数是常量并且定义或描述了合约的行为,使用第一种方法比较方便。 如果基类构造函数的参数依赖于派生合约,那么必须使用第二种方法。

参数必须在两种方式中(继承列表或派生构造函数修饰符样式)使用一种 。 在这两个位置都指定参数则会发生错误。

如果派生合约没有给所有基类合约指定参数,则这个合约必须声明为抽象合约。 在这种情况下,当另一个合约从它派生出来时,另一个合约的继承列表或构造函数必须为所有还没有指定参数的基类提供必要的参数(否则,其他合约也必须被声明为抽象的)。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

//base contract
contract Animal  {
   string name;

   constructor(string memory _name){
      name = _name;
   }
}
//爬行动物是动物
abstract contract Reptile is Animal{}

contract Snake is Reptile {
   //这是一只眼镜蛇
   constructor() Animal("cobra"){}
}

在这里插入图片描述

当继承层次结构中有多个构造函数时,继承线性化特别重要。 构造函数将始终以线性化顺序执行,无论在继承合约的构造函数中提供其参数的顺序如何。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

//base contract
contract Animal  {
   string name;
   constructor(string memory _name){
      name = _name;
   }
}
//爬行动物是动物
contract Reptile {
   string public name;
   constructor(string memory _name){
      name = _name;
   }
}
//蛇是爬行动物,又属于动物
//  构造函数以以下顺序执行:
//  1 - Reptile
//  2 - Animal
//  3 - Snake
contract Snake is Reptile,Animal {
   //这是一只眼镜蛇 多个基类使用空格隔开
   constructor() Reptile("pa") Animal("cobra"){}
}

//  构造函数以以下顺序执行:
//  1 - Animal
//  2 - Reptile
//  3 - Snake
contract Snake is Animal,Reptile {
   //这是一只眼镜蛇 多个基类使用空格隔开
   constructor() Animal("cobra") Reptile("pa") {}
}

//  构造函数仍然以以下顺序执行:
//  1 - Animal
//  2 - Reptile
//  3 - Snake
contract Snake is Animal,Reptile {
   //这是一只眼镜蛇 多个基类使用空格隔开
   constructor() Reptile("pa") Animal("cobra") {}
}


}

在这里插入图片描述

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

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

相关文章

Java-数据库范式与表关系

数据库范式 数据库范式简介 什么是范式(NF NormalForm) ● 范式是符合某一种设计要求的总结 在数据库中表的设计,必须保证其合理性 ● 数据库表的设计关系整个系统的架构,关系到后续的开发效率和运行效率 如何设计合理的数据库…

【leetcode】二叉树的最近公共祖先

一、题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也…

在职位招聘数据处理中使用Loess回归曲线以及分箱、回归、聚类方法 检查离群点及光滑数据【数据挖掘机器学习】

文章目录一.需求分析二.使用局部回归(Loess)曲线(增加一条光滑曲线到散布图)方法处理数据三.使用分箱、回归、聚类方法 检查离群点及光滑数据;一.需求分析 本文主题:使用局部回归(Loess&#x…

Jmeter(十九):nmon性能系统监控工具

一、Nmon介绍 Nmon得名于 Nigel 的监控器,是IBM的员工 Nigel Griffiths 为 AIX 和 Linux 系统开发的,使用 Nmon 可以很轻松的监控系统的CPU、内存、网络、硬盘、文件系统、NFS、高耗进程、资源和 IBM Power 系统的微分区的信息 Nmon是一款计算机性能系…

【JavaEE】HTTP + HTTPS(Part2 )

努力经营当下,直至未来明朗! 文章目录【HTTP响应详解】1. 认识状态码2.认识响应“报头”header3.认识响应“正文”body【通过 Java socket 构造 HTTP 请求】三、HTTPS四、Tomcat:http服务器THINK一个人最大的痛苦来源于对自己无能的愤怒。 【…

Pycharm SQL 警告:SQL dialect is not configured.

Pycharm SQL 警告:SQL dialect is not configured. 文章目录Pycharm SQL 警告:SQL dialect is not configured.Unable to resolve symbol XXX在我们编写python代码的时候,不免会在代码里面写入自己写的sql语句,因为很少有orm框架能…

JVM Java内存模型(JMM)

很多人将Java内存结构与Java内存模型傻傻分不清,Java内存模型是Java memory model(JMM)的意思。简单地说,JMM定义了一套在多线程的环境下读写共享数据(比如成员变量、数组)时,对数据的可见性、有…

浪潮开务数据库陈磊:布局数字能源,创新助力 “双碳”

​当前,碳中和、碳达峰无疑是国际社会最关注的热点之一。2021 年两会上,我国提出:二氧化碳排放力争于 2030 年前达到峰值,努力争取 2060 年前实现碳中和。“双碳” 目标的提出将推动产业转型升级,提高经济增长质量&…

【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点

目录 一、力扣第206题:反转链表 1.思路一 2.思路二 二、力扣第876题:链表的中间结点 1.思路一 2.思路二 总结 一、力扣第206题:反转链表 题目链接:206. 反转链表 - 力扣(Leetcode) 题目描述&#xff1…

gitee学习笔记(使用命令行上传、拉取资料)

1、创建一个仓库(比如命名为firstgit) 2、在文件夹中准备好要上传的资料 3、单击鼠标右键,打开Git Bash Here 进行命令行操作(当然,前提是需要安装git客户端,可去官网安装) 4、上传文件 ①git init //文件初始…

【mybatis-plus】自定义多数据源,动态切换数据源事务失效问题

背景 做了一个和navicat一样的工具,web版工具,然后数据库链接信息都是存在一个主数据库表的里,所以这里涉及到了动态切换数据源,以及一些事务等。今天说下多数据源切换时,事务失效。 目录 一、常见的事务失效 Transac…

大数据必学Java基础(一百一十二):开发案例之登录验证

文章目录 开发案例之登录验证 一、准备实体类 二、准备一些页面和静态资源

Spring boot day1

Maven 进阶 spring boot 框架 spring boot 相比于SSM框架的优缺点 优点: 创建独立的sping应用程序内嵌的tomcat,无需部署war文件简化的maven配置自动配置spring提供生产就绪型功能,如指标,健康检查和外部配置 特性:…

3.1 卷积神经网络基础

文章目录计算机视觉的发展历程卷积神经网络卷积(Convolution)卷积计算填充(padding)步幅(stride)感受野(Receptive Field)多输入通道、多输出通道和批量操作飞桨卷积API介绍卷积算子…

碰焊机触摸屏软件开发

1 软件需求 人机界面为MCGS 10寸触摸屏1062KW,接口为RS232/RS484/以太网,供电电源为24V。机触摸屏的功能为机器人的基本状态信息显示和对机器人的控制及参数给定。 目前设计的小车分成两栏共10格,需要将对应的触摸屏大致分成相应的10大格&a…

【嵌入式】AI落地部署技能

针对不同平台对生成的模型进行转换,也就是俗称的parse、convert,即前端解释器针对转化后的模型进行优化在特定的平台(嵌入端或者服务端)成功运行已经转化好的模型在模型可以运行的基础上,保证模型的速度、精度和稳定性用C、cuda写算子(预处理…

AWS-Eventbridge-事件总线实践

aws eventbridge 功能主要使用场景为,针对账号发生各种事件,发生告警,可以发送sns告警,也可以配置发送到当前区域或者其他账号当前区域的事件总线上汇总,再做下一步规划eventbridge 事件总线类似与整个事件的一个目录集…

机器学习——03决策树算法

机器学习——03决策树算法 参考资料 AIlearningMachine-Learning-in-Action庞善民.西安交通大学机器学习导论2022春PPT 具体算法的原理步骤请参考本人的另一篇博文:[机器学习导论]—— 第四课——决策树 一、信息熵与信息增益 🔥信息熵 信息熵使信息…

中小企业OA系统的设计与实现

开发工具(eclipse/idea/vscode等): 数据库(sqlite/mysql/sqlserver等): 功能模块(请用文字描述,至少200字): 模块划分:通知类型模块、通知信息模块、部门模块、员工模块、考勤模块、工资模块、奖惩类型、奖惩信息、请假…

USACO开赛!这份参赛指引必看!

美国信息学奥赛USACO 2022 – 2023赛季首场比赛于明日(12月16日)开始!这份参赛指引,一定要认真看噢~ 第一步:打开 USACO 官网:http://www.usaco.org/,点击【注册新账号】,开始注册账…