Solidity基础五

news2024/11/27 8:38:12

暂时的一事无成也代表将来万事皆有可能!

目录

一、对Solidity文件的理解

二、Solidity的导sol文件(库、合约)

三、Solidity的继承

1.继承的分类

2.继承的可见性 

3.父合约构造函数的传参

4.调用父合约成员

5.重写

四、Solidity的抽象合约

五、Solidity接口合约

实现接口

六、Solidity的库

库合约的存在形式

七、Solidity的对象 


一、对Solidity文件的理解

Solidity文件是Solidity语言文件,里面包含Solidity语言代码,文件名以.sol结尾。

一个sol文件可以创建(含有)许多的contract(合约),不单单只有一个

那同一个sol文件中的各个合约如何实现交互呢?

不同的sol文件的各个合约又如何进行交互呢?

答案是:继承和对象

接下来就要讲到交互的方式

二、Solidity的导sol文件(库、合约)

通过

关键字:import  sol文件名.sol  (文件的相对位置)

可以进行导入外部sol文件,导的sol文件和本身的sol文件相当于变成同一个sol合约 

  

具体操作

    import关键字使用:导入其他源文件

    1. imporot "solidity文件名"   :导入该文件全局作用域到当前全局作用域中

    2.import * as 别名 "solidity文件名"   : 导入该文件全局作用域到当前全局作用域中

    并起一个文件别名,通过别名可创建导入文件下某一合约的对象

    3.import "solidity文件名"as 别名 :和2效果一样,书写比2简单,经常用

    4.imoport {合约名 as 别名,合约名} from "solidity文件夹名" :导入导入文件夹名

    下的某几个合约到该文件中

三、Solidity的继承

像java类的继承一样,在solidity中,那就是合约的继承

Solidity 语言是一种面向对象的编程语言,提供了对合约继承的支持,继承是扩展合约功能的一种方式。

Solidity 语言的合约继承通过关键字 is 来实现。

继承的关键字:is

 

继承的本质:继承的实现方案是代码拷贝,所以合约继承后,部署到网络时,将变成一个合约,代码从父类拷贝到子类中。

被继承的合约我们称之为父合约(基类合约),继承了的合约称之为子合约(派生合约)

Solidity中合约继承的重要特点

  • 派生合约可以访问父合约所有非私有private的成员,包括内部方法和状态变量。但是不允许使用this(代表需要使用创建对象的形式来访问external的东西)
  • 如果函数签名保持不变,则允许函数重写,如果派生合约与父合约函数对应输出参数不同,编译将失败
  • 使用super关键字或父合约名调用父合约函数,或者直接调用
  • 在多重继承的情况下,使用super的父合约函数调用,优先选择被最多继承的合约

1.继承的分类

单继承:

一个合约继承一个合约

例如:

contract X {}

contract A is X{}

多继承

一个合约被多个合约继承

例如

contract X {}

contract A is X{}

contract B is X{}

多层继承

但可以有爷爷,祖先,而这就是多重继承

合约被合约继承,继承的合约又被另一个合约继承

注意事项:

当多重继承合约时,这些父合约中不允许出现相同的状态变量名

当多重继承合约时,这些父合约中允许出现相同的函数名,事件名,修改器名

例如

contract X {}

contract A is X{}

contract B is A{}

多重继承示例

Solidity 语言提供了对合约继承的支持,而且支持多重继承。

Solidity 语言的多重继承采用线性继承方式。继承顺序很重要,判断顺序的一个简单规则是按照“最类似基类”到“最多派生”的顺序指定基类。

第一种情况:基类 X,Y 没有继承关系,派生类 Z 继承了 X,Y。

X  Y
/  \
\  /
 Z

多重继承格式

子合约 is 父合约1,父合约2····{

}

contract X {}

contract A {}

contract B is X,A{}

2.继承的可见性 

子合约不能访问父合约的private修饰的私有成员

子合约可以直接访问访问父合约的所有非私有(public、internal)成员

子合约不能直接访问父合约的external修饰的外部成员,因为子合约不能对父合约的东西使用this,想要访问到就必须创建父合约对象的方式来调用间接访问

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract A{
  uint stateVar;//状态变量默认是internal权限
  function somePublicFun() public{}
  function someInternalFun() internal{}
  function somePrivateFun() private{}
  function someExternalFun() external{}
}

contract B is A{
  function call() public {
    //访问父类的`public`方法
    somePublicFun();

    //访问父类的状态变量(状态变量默认是internal权限)
    stateVar = 10;

    //访问父类的`internal`方法
    someInternalFun();

    //不能访问`private`
    //somePrivateFun();
    A a = new A();
    a.someExternalFun();
  }
}

 3.父合约构造函数的传参

派生的合约初始化前需要调用所有父合约的构造函数,并且还需要提供所有父合约所需的参数

提供父合约构造函数需要的所有参数,有两种提供方式

第一种称

在声明继承的时候

派生合约名 is 父合约名(参数) {        }

此方式对于构造函数是常量情况的时候比较方便,可以直接说明合约的行为

第二种称

在派生合约的构造器中

constructor(参数列表) 父合约名(参数列表){

}  

注意:如果是多重继承,那么同理

派生合约名 is 父合约名(参数),·····{        }

constructor(参数列表) 父合约名(参数列表),·······{

}  

4.调用父合约成员

当一个合约从多个合约继承时,在区块链上只有一个合约被创建,所有基类合约的代码被编译到创建的合约中。这意味着对基类合约函数的所有内部调用也只是使用内部函数调用

1.直接调用和使用(适用于单继承,或者其他继承但名不冲突的情况下)

2. 利用父合约名(这样更好,适用多种类型的继承)

3.super关键字  (使用super可以访问父合约的函数,但不能访问状态变量,如果是多层和多重继承,那么它将调用所有的父类的该名的方法)

5.重写

派生合约不可以再声明已经是基类合约中可见的状态变量具有相同的名称。即状态变量不允许重写

但是函数名可以是相同的,假如函数名相同参数列表不同,则定为是函数重载

若函数名相同,参数类型也相同,则定为是函数重写

在子合约中允许重写函数,但不允许重写返回参数,即返回值类型和个数不能修改

重写步骤

1.父合约要被重写的函数必须加上能被重写修饰符 virtual 

2.子合约重写的函数上面必须加上重写修饰符 override 

 

温馨提示:

midifier函数修改器(后面讲)也会随着父合约被继承从而被继承,被继承后,在子合约中我们还可以对父合约中的修改器进行重写和使用

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Person{
  string public name;
  uint public age;
  function getSalary() external pure virtual returns(uint){
    return "unkown";
  }
}
contract Employee is Person{
  function getSalary() external pure override returns(uint){
    return 3000;
  }
}

四、Solidity的抽象合约

抽象合约和其他语言的抽象类相似,它是一个合约中没有函数体(具体函数实现)的函数(直接以;结尾, 没有函数体标识符{})的合约

关键字: abstract

 

使用格式:

abstract contract 合约名 {

        状态变量;

        未实现的函数;

        ·················

}

 

抽象合约的作用:

抽象合约 abstract 的作用是将函数定义和具体实现分离,从而实现解耦、可拓展性,其使用规则为

简单来说:抽象合约定义后,是专门用来继承用的,它相比于其他的继承做了一种强迫的事情,就是子合约必须重写抽象合约里面的所有函数

abstract还可以避免子合约不对父合约进行构造函数传参的问题

 注意事项

  • 当合约中有未实现的函数时,则合约必须修饰为abstract;
  •  当合约继承的基合约中有构造函数,但是当前合约并没有对其进行传参时,则必须修饰为abstract;
  • abstract合约中未实现的函数必须在子合约中实现,即所有在abstract中定义的函数都必须有实现;
  • abstract合约不能单独部署,必须被继承后才能部署;
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;

abstract contract Animal {
    string public species;
    constructor(string memory _base) {
        species = _base;
    }
}

abstract contract Feline {
    uint public num;
    function utterance() public pure virtual returns (bytes32);

    function base(uint _num) public returns(uint, string memory) {
        num = _num;
        return (num, "hello world!");
    }
}

// 由于Animal中的构造函数没有进行初始化,所以必须修饰为abstract
abstract contract Cat1 is Feline, Animal {
    function utterance() public pure override returns (bytes32) { return "miaow"; }
}

contract Cat2 is Feline, Animal("Animal") {
    function utterance() public pure override returns (bytes32) { return "miaow"; }
}

五、Solidity接口合约

接口和抽象合约类似,也是只定义函数,不实现函数,由实现接口的合约来实现,不同的是,同时还有以下限制

不能继承其他合约或者接口

不能定义构造器

不能定义变量

不能定义结构体

不能定义枚举类

相当于单单定义函数

  

还有一个相对于抽象合约的特点就是,定义函数的时候它不需要写virtual,且函数修饰符都是external

 

接口关键字:interface

定义格式:

interface 合约名 {        

        定义接口函数1;

        ·········;

        定义接口函数n;

}

实现接口

实现接口和继承一样,使用关键字is

实现接口函数用override修饰符

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

interface Bank{
function outputMoney(uint _money) external ;
function intputMoney(uint _money) external ; 
}

contract own is Bank {
uint public money;
function outputMoney(uint _money) external override {
    money+=_money;
}

function intputMoney(uint _money) external override {
    money-=_money;
}
}

六、Solidity的库

Solidity 智能合约中通用的代码可以提取到库 library,以提高代码的复用性和可维护性。

库 library 是智能合约的精简版,就像智能合约一样,位于区块链上,包含可以被其他合约使用的代码。

库合约一般定义成public和internal权限,定义成 external 毫无意义,因为库合约函数只在内部使用,不独立运行。同样,定义成 private 也不行,因为其它合约无法使用。

对比普通合约来说,库有以下限制

  • 无状态变量
  • 不能继承和被继承
  • 不能接收以太币
  • 不能销毁一个库

代表只能有函数 

 

关键字:library

格式:

library 库名{

        库方法

        ·····

}

使用库 library 的合约,可以将库合约视为隐式的父合约,当然它们不会显式的出现在继承关系中。也就是不用写 is 来继承,直接可以在合约中使用。

库的使用

如果库和使用库的合约在同一个sol文件,那么即可直接用

第一种方式

库名.库合约函数(参数值1,参数值2····)        的方式直接调用库里面的函数 

第二种方式

再使用using 库合约名 for 数据类型

使用 using for 语法附着的数据类型,在使用的时候,可以直接用 <variable>.<method> 的形式调用,而且省略代表自己的第一个参数。

格式:

using 库名 for 使用的参数类型    

然后使用

格式: 使用的参数类型对应的变量.函数名(参数值2 )      //该变量默认为第一个参数

如果库的使用库的合约不在同一个sol文件,那么需要

先导包import

库合约的存在形式

库 library 有两种存在形式:

  •  内嵌(embedded):当库中所有的方法都是internal时,此时会将库代码内嵌在调用合约中,不会单独部署库合约;
  •  链接(linked):当库中含有external或public方法时,此时会单独将库合约部署,并在调用合约部署时链接link到库合约。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library Math {
   function find(uint[] storage arr, uint val) internal view returns(uint){
      for (uint i=0; i<arr.length; i++) {
         if (arr[i] == val) {
            return i;
         }
      }
      revert("not found");
   }
}

contract MathTest {
    //直接使用
    uint[] a;

    uint b;

    function tests() public view {
        Math.find(a,b);
    }

   //using for使用
   // 将 libray Math 附着到类型 uint[]
   using Math for uint[];

   uint[] arr = [1,2,3];

   function test() external view returns(uint){
      return arr.find(2);
   }
}

七、Solidity的对象 

Solidity的对象可以帮助我们访问到非继承合约里面的函数,但不能访问到里面的状态变量,它好比于是两个合约之间的媒人

对象的创建方式

合约名  对象名 = new 合约名() 

这就完成了该合约对象的创建,创建完该对象后,那么创建该对象的合约就可以使用这个对象去调用对象对应合约的函数

常用于

子合约访问父合约external的状态变量和函数

使用非继承关系合约的函数 

  

    具体操作

    1. solidty文件夹名 对象名= new solidity文件夹名()

    2.文件别名 对象名=new 文件别名()

    3.文别名.合约名 对象名 =new 文别名.合约名()

    4. 合约别名 对象名 =new 合约别名()

   5. 合约名 对象名 =new 合约名()

    当然也可以不起别名,那就用solidity文件夹名,或合名

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Math {
    int[2] arr;
    function aa() public view returns(int[2] memory){
        return arr;
    }
}

contract MathTest {
    //创建Math合约对象
    Math m = new Math();

    function get() public view returns(int[2] memory){
    //调用Math合约的东西
    return m.aa();
    }
}

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

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

相关文章

Solidity基础八

别慌&#xff0c;月亮也在大海某处迷茫 目录 一、Solidity 编程风格 1. 代码布局 2. 代码中各部分的顺序 3. 命名约定 二、Solidity 智能合约编写过程 1. solidity Hello World 2. 版本声明 3. 导入声明 4. 合约声明 三、Solidity 合约结构 智能合约 Test 四、So…

Solidity基础六

生活本来就是平凡琐碎的&#xff0c;哪有那么多惊天动地的大事&#xff0c;快乐的秘诀就是不管对大事小事都要保持热情 目录 一、Solidity的特殊变量(全局) 二、Solidity的不可变量 immutable的赋值方式 三、Solidity的事件与日志 事件和日志加深理解 四、Solidity的异常…

EMLP2021 | Google大模型微调经典论文prompt tuning

一、概述 title&#xff1a;The Power of Scale for Parameter-Efficient Prompt Tuning 论文地址&#xff1a;https://arxiv.org/abs/2104.08691 代码&#xff1a;GitHub - google-research/prompt-tuning: Original Implementation of Prompt Tuning from Lester, et al, …

系列一、RuoYi前后端分离(登录密码加密)

一、部署前后端服务 http://doc.ruoyi.vip/ruoyi-vue/ 二、现象 若依前后端环境分离版本&#xff0c;本地部署好前后端环境后&#xff0c;访问登录接口密码是明文的&#xff0c;这样显然hi不安全的&#xff0c;如下图所示&#xff1a; 三、解决方法 3.1、加密流程 ①、后端…

Linux-0.11 文件系统namei.c详解

Linux-0.11 文件系统namei.c详解 模块简介 namei.c是整个linux-0.11版本的内核中最长的函数&#xff0c;总长度为700行。其核心是namei函数&#xff0c;即根据文件路径寻找对应的i节点。 除此以外&#xff0c;该模块还包含一些创建目录&#xff0c;删除目录&#xff0c;创建目…

Day2:Windows网络编程-TCP

今天开始进入Windows网络编程的学习&#xff0c;在学习的时候总是陷入Windows复杂的参数&#xff0c;纠结于这些。从老师的讲解中&#xff0c;这些内容属于是定式&#xff0c;主要学习写的逻辑。给自己提个醒&#xff0c;要把精力放在正确的位置&#xff0c;不要无端耗费精力。…

【JavaScript】文件分片上传

文章目录 普通文件上传分片上传整体流程技术点分析文件选择方式隐藏input框&#xff0c;自定义trigger拖拽上传 分片动态分片 计算哈希workerrequestIdleCallback抽样 请求并发控制进度展示手动中止/暂停 合并流式并发合并 反思分片命名问题并发控制代码实现的问题 参考文献 普…

ChatGPT桌面客户端支持gpt4模型,附使用说明

#软件核心功能&#xff1a; 1、支持OpenAI官方秘钥及API2D双秘钥使用&#xff1b;如果全局魔法&#xff0c;可以自己用官方秘钥&#xff1b;没魔法国内可直接使用API2D秘钥&#xff1b; 2、内置GPT4模型选项&#xff0c;如果你的官方秘钥支持可直接使用&#xff1b;你也可以注册…

【Labview如何显示数据库表格中的内容】

Labview如何显示数据库表格中的内容 前提操作思路框图 前提 已经成功将数据库与Labview相连接&#xff0c;若还没有链接可以查看&#xff1a;Labview与SQL Server互联 进行操作 操作 思路 首先创建一个表格控件&#xff0c;通过一个按钮启动程序&#xff0c;通过程序调用数…

SAP MM 根据采购订单反查采购申请

如何通过采购订单号查询到其前端的采购申请号。 首先从采购申请的相关报表着手&#xff0c;比如ME5A, 发现它是可以满足需求的。 例如&#xff1a;如下的采购订单&#xff0c; 该订单是由采购申请10003364转过来的。 如果想通过这个采购订单找到对应的采购申请&#xff0c;在…

Packet Tracer – 配置命名标准 IPv4 ACL

Packet Tracer – 配置命名标准 IPv4 ACL 地址分配表 设备 接口 IP 地址 子网掩码 默认网关 R1 F0/0 192.168.10.1 255.255.255.0 N/A F0/1 192.168.20.1 255.255.255.0 N/A E0/0/0 192.168.100.1 255.255.255.0 N/A E0/0/1 192.168.200.1 255.255.2…

第五十五天学习记录:C语言进阶:动态内存管理Ⅲ

柔性数组 C99中&#xff0c;结构中的最后一个元素允许是未知大小的数组&#xff0c;这就叫做柔性数组成员。 柔性数组的特点&#xff1a; 。结构体中的柔性数组成员前面必须至少有一个其他成员。 。sizeof返回的这种结构大小不包括柔性数组的内存。 。包含柔性数组成员的结构…

【C++学习】智能指针

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《C学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 智能指针 &#x1f96e;智能指针&#x1f362;为什么需要智能指针&#x1f362;RAII &#x1f96e;au…

chatgpt赋能python:Python自动开机:提高效率的必备工具

Python 自动开机&#xff1a;提高效率的必备工具 随着科技的发展&#xff0c;计算机在我们的日常生活中扮演了越来越重要的角色。为了提高工作效率和使用体验&#xff0c;越来越多的人开始探索利用自动化工具来简化日常操作。 Python 称得上是自动化领域中的一把利器。通过代…

SAP-MM费用类采购通过物料组确定科目

一、WRX的配置&#xff0c;分两类GR/IR科目&#xff1a; 1、做库存管理物料的GR/IR科目&#xff0c;需要配置评估类&#xff0c;此评估类就是物料主数据里配置的评估类&#xff1b; 2、非库存管理费用化物料的GR/IR科目&#xff0c;如固定资产、办公用品、低值易耗品等等&#…

chatgpt赋能python:Python生成C代码:如何用Python快速高效地生成C代码

Python生成C代码&#xff1a;如何用Python快速高效地生成C代码 在现代编程中&#xff0c;有许多原因需要编写C代码。C是一种高性能语言&#xff0c;它允许程序员直接操作计算机的硬件。但是&#xff0c;编写C代码需要花费大量的时间和精力。幸运的是&#xff0c;Python可以帮助…

Spring Boot问题汇总

1.IDEA里yaml文件编辑时没有提示 网上很多教程说在设置里的File Types里把yaml格式加入到关联中 但其实我打开IDEA默认就是这么设置的&#xff0c;所以并没有什么用处。 不过在翻看这篇教程&#xff08;IDEA创建yml文件不显示小树叶创建失败问题的解决方法-eolink官网&#x…

网络安全学习心得分享~

我的学习心得&#xff0c;我认为能不能自学成功的要素有两点。 第一点就是自身的问题&#xff0c;虽然想要转行学习安全的人很多&#xff0c;但是非常强烈的想要转行学好的人是小部分。而大部分人只是抱着试试的心态来学习安全&#xff0c;这是完全不可能的。 所以能不能学成并…

【Python】字符串操作

知识目录 一、写在前面✨二、字符串逆序三、打印菱形四、总结撒花&#x1f60a; 一、写在前面✨ 大家好&#xff01;我是初心&#xff0c;很高兴再次跟大家见面。&#xff08;相遇就是缘分啊&#xff09; 今天跟大家分享的文章是 Python中的字符串操作 &#xff0c;希望能帮助…

SAP-物料主数据-质量管理视图字段解析

过账到质检库存&#xff1a;要勾选&#xff0c;否则收货后库存不进入质检库存HU检验&#xff1a;收货到启用HU管理的库位时产生检验批&#xff0c;例如某个成品物料是收货到C002库位&#xff0c;该库位启用了HU管理&#xff0c;那么此处要勾选。但是如果勾选了&#xff0c;却收…