《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];
}
}
这个 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);
}
}
在这里 LibraryDemo.structData private libObj;
是创建了一个 LibraryDemo 中 structData 结构体类型的变量 libObj,在之后的函数中,分别使用了 LibraryDemo 中的 insertData 方法传入这个 libObj 对 libObj 数据进行插值,但是这个有点冗长了,那怎么使用 using for 进行修改呢?
三、using for 使用
其实使用 using for 只需要指定为某一个类型的数据 变量 附加你所引入的 library 即可。那这句话是什么意思呢?
其实就是指你创建一个变量,为这个变量附上你所需要使用的库合约,那么这个变量就可以操作这个 import 过来的合约方法了。(为什么前面说那么多不一句话总结?那是因为我写的文章可能需要逻辑,觉得有逻辑的话才好懂,而不是需要读者自己去“悟”,不过也有可能你不认同的逻辑)
那怎么写呢?如下是一个示例:
using LibraryDemo for LibraryDemo.structData;
以上示例表示 使用 LibraryDemo 这个引入的合约 附加 到 LibraryDemo 中的 structData 这个结构体的类型变量上,以后只要是这个类型的变量就可以使用 LibraryDemo 合约中的方法。
接着我们是不是需要创建一个这个 structData 类型的变量了?
所以代码可以写成(在之前的代码中进行修改就可以了,等下会贴出完整代码的):
LibraryDemo.structData private libObj;//完全不用修改
接着就是修改调用方法了,之前 CallLib 中的方法 insertName 是如下形式:
function insertName(string memory _name,uint32 _age)public{
LibraryDemo.insertData(libObj,_name,_age);
}
调用方法有些冗长(当然是对比之后感觉长),那怎么更改呢?
此时修改方法如下:
function insertName(string memory _name,uint32 _age)public{
libObj.insertData(_name,_age);
}
因为 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);
}
是不是感觉代码短了很多了呢?并且知道用法后感觉这种方式非常简明(以后就可以体会到了)。
接下来部署后使用:
没毛病,完成。
完整的 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);
}
}
四、注意
需要引入的必须是库,我们可以看个示例:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract UsingDemo{
function add(uint64 num1,uint64 num2)pure public returns(uint64){
return num1+num2;
}
}
以上合约中有一个方法名为 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);
}
}
从以上代码中我们可以得知,我使用了 using 读 uint64 数据类型做附加,若成功,我只需要使用一个 uint64 的变量调用 add 方法传入要加的值就可以对这个类型的某个变量做自增操作了,那么此时编译后将会出现错误:
将会提示类型错误,叫我们输入一个 Library 的名称,那说明我们在使用 using 时必须使用 库 合约。