• 二、solidity 基础进阶(2.2)—— 库合约的 using for《实战NFT web3 solidity(新版本0.8.+)》


    web3 solidity0.8.+版本(持续更新新版本内容) 基础到实战NFT开发》会及时更新新版本 solidity 内容,以及完成最终的 NFT 实战商业项目部分。

    注:由于是付费专栏内容,若有错误请及时联系@1_bit,博客链接:https://blog.csdn.net/A757291228 ,或在文章下留言,收到后将会对错误进行改正,若是版本更新导致的问题也希望大家对错误进行提交,尽力去保证付费用户该得到的权益。

    文章目录可查看:目录(文章更新中…)
    更新内容将会在目录中更新…

    友情提示:本系列文章读者最好学过一门编程语言,面向对象语言更佳,文章所有代码将会完整贴出。

    一、附加 Using for

    在我们使用 library 库合约时是不是有点略过于麻烦了?例如还需要直接通过合约去调用某个方法,感觉这样编写过于冗长,现在通过使用 using for 可以很方便的解决这个“麻烦”。

    使用 Using for 需要有个前提,那就是你必须 import 了库合约(必须是库),否则无法使用 using for。毕竟 using for 就是用来解决有关库合约 的某个问题的,没有因何来果。

    我们直接用上一节的内容进行修改即可,不过在此之前先要简单复习一下上一节的代码。

    二、通过上一节的内容进行修改(复习)

    在上一届中我们是创建了一个 library 名叫 LibraryDemo,代码是这样的:

    pragma solidity ^0.8.7;
    
    library LibraryDemo{
        struct structData{
            mapping(string=>uint32) map;
        }
    
        function insertData(structData storage self,string memory _name,uint32 _age)public {
            self.map[_name]=_age;
        }
    
        function get(structData storage self,string memory _name)view public returns(uint32){
            return self.map[_name];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这个 library 定义了一个结构体,里面有一个成员 mapping 类型的数据 map,并且定义了两个函数,一个 insertData 用于存数据,另一个 get 用来取数据,并且在此还需要注意他们所传的参数是一个指针类型的 structData 类型的数据,在此要注意这个数据,等下会讲解到的 using for 知识点有与之相关的内容。

    接下来我们还有一个引入 库合约 的合约,我们命名为 CallLib,代码是这样的:

    contract CallLib{
        LibraryDemo.structData private libObj;
    
        function insertName(string memory _name,uint32 _age)public{
            LibraryDemo.insertData(libObj,_name,_age);
        }
    
        function get(string memory _name)view public returns(uint32){
            return LibraryDemo.get(libObj,_name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里 LibraryDemo.structData private libObj; 是创建了一个 LibraryDemo 中 structData 结构体类型的变量 libObj,在之后的函数中,分别使用了 LibraryDemo 中的 insertData 方法传入这个 libObj 对 libObj 数据进行插值,但是这个有点冗长了,那怎么使用 using for 进行修改呢?

    三、using for 使用

    其实使用 using for 只需要指定为某一个类型的数据 变量 附加你所引入的 library 即可。那这句话是什么意思呢?

    其实就是指你创建一个变量,为这个变量附上你所需要使用的库合约,那么这个变量就可以操作这个 import 过来的合约方法了。(为什么前面说那么多不一句话总结?那是因为我写的文章可能需要逻辑,觉得有逻辑的话才好懂,而不是需要读者自己去“悟”,不过也有可能你不认同的逻辑)

    那怎么写呢?如下是一个示例:

    using LibraryDemo for LibraryDemo.structData;
    
    • 1

    以上示例表示 使用 LibraryDemo 这个引入的合约 附加 到 LibraryDemo 中的 structData 这个结构体的类型变量上,以后只要是这个类型的变量就可以使用 LibraryDemo 合约中的方法。

    接着我们是不是需要创建一个这个 structData 类型的变量了?

    所以代码可以写成(在之前的代码中进行修改就可以了,等下会贴出完整代码的):

    LibraryDemo.structData private libObj;//完全不用修改
    
    • 1

    接着就是修改调用方法了,之前 CallLib 中的方法 insertName 是如下形式:

    function insertName(string memory _name,uint32 _age)public{
       LibraryDemo.insertData(libObj,_name,_age);
    }
    
    • 1
    • 2
    • 3

    调用方法有些冗长(当然是对比之后感觉长),那怎么更改呢?

    此时修改方法如下:

    function insertName(string memory _name,uint32 _age)public{
        libObj.insertData(_name,_age);
    }
    
    • 1
    • 2
    • 3

    因为 libObj 是我们刚刚创建的 structData 类型变量,那么即表示这个变量 libObj 已经附加了库 LibraryDemo ,可以对库中的方法进行调用,那么在以上代码中使用 libObj 调用 insertData 是允许的。

    那 insertData 不是三个参数嘛?第一个参数是 structData storage self ,为什么此时使用 libObj 调用 insertData 方法后是两个参数呢?

    这是因为 libObj 本身就代表着第一个参数,这样说明白了吧,那么此时 get 方法可以修改成如下:

    function get(string memory _name)view public returns(uint32){
        return libObj.get(_name);
    }
    
    • 1
    • 2
    • 3

    是不是感觉代码短了很多了呢?并且知道用法后感觉这种方式非常简明(以后就可以体会到了)。

    接下来部署后使用:
    在这里插入图片描述
    没毛病,完成。

    完整的 CallLib 方法修改后如下:

    // SPDX-License-Identifier:MIT
    
    pragma solidity ^0.8.7;
    
    import "./LibraryDemo.sol";
    
    contract CallLib{
        using LibraryDemo for LibraryDemo.structData;
        
        LibraryDemo.structData private libObj;
        function insertName(string memory _name,uint32 _age)public{
            libObj.insertData(_name,_age);
        }
    
        function get(string memory _name)view public returns(uint32){
            return libObj.get(_name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    四、注意

    需要引入的必须是库,我们可以看个示例:

    // SPDX-License-Identifier:MIT
    
    pragma solidity ^0.8.7;
    
    contract UsingDemo{
        function add(uint64 num1,uint64 num2)pure public returns(uint64){
            return num1+num2;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    以上合约中有一个方法名为 add,接收两个参数做加法运算后返回,接着我们在另外一个合约中使用 import 进行导入:

    // SPDX-License-Identifier:MIT
    
    pragma solidity ^0.8.7;
    
    import "./LibraryDemo.sol";
    
    contract CallLib{
        using UsingDemo for uint64;
        
        uint64 num=0;
        function add(uint64 _num)public returns(uint64){
            return num.add(_num);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    从以上代码中我们可以得知,我使用了 using 读 uint64 数据类型做附加,若成功,我只需要使用一个 uint64 的变量调用 add 方法传入要加的值就可以对这个类型的某个变量做自增操作了,那么此时编译后将会出现错误:
    在这里插入图片描述

    将会提示类型错误,叫我们输入一个 Library 的名称,那说明我们在使用 using 时必须使用 库 合约。

  • 相关阅读:
    基于云存储技术的仓储管理系统
    AMD AFMF不但能用在游戏,也适用于视频
    bionic-信号量&backtrace
    Curve 文件系统的重要特点之一就是适用于海量文件存储
    PaddleSeg(1)配置文件详解
    电商平台图片相似度搜索怎么实现的?
    JS中的元素样式
    【ARM裸机】ARM入门
    C/C++算法入门 | 查找元素
    算法day22|235,701,450
  • 原文地址:https://blog.csdn.net/A757291228/article/details/127135277