Solidity语言学习笔记————37、Using for

本文介绍如何使用Solidity中的usingAforB指令将库函数扩展到任意类型或基本类型上,以此实现代码复用和增强数据类型的功能。通过具体例子展示了如何对自定义结构和数组类型进行扩展。

指令using A for B;用来附着库里定义的函数(从库A)到任意类型B。这些函数将会默认接收调用函数对象的实例作为第一个参数。语法类似,python中的self变量一样。

using A for *的效果是,库A中的函数被附着在做任意的类型上。

在这两种情形中,所有函数,即使那些第一个参数的类型与调用函数的对象类型不匹配的,也被附着上了。类型检查是在函数被真正调用时,函数重载检查也会执行。

using A for B;指令仅在当前的作用域有效,且暂时仅仅支持当前的合约这个作用域,后续也非常有可能解除这个限制,允许作用到全局范围。如果能作用到全局范围,通过引入一些模块(module),数据类型将能通过库函数扩展功能,而不需要每个地方都得写一遍类似的代码了。

下面我们来换个方式重写set的例子。

pragma solidity ^0.4.16;

// This is the same code as before, just without comments
library Set {
  struct Data { mapping(uint => bool) flags; }

  function insert(Data storage self, uint value)
      public
      returns (bool)
  {
      if (self.flags[value])
        return false; // already there
      self.flags[value] = true;
      return true;
  }

  function remove(Data storage self, uint value)
      public
      returns (bool)
  {
      if (!self.flags[value])
          return false; // not there
      self.flags[value] = false;
      return true;
  }

  function contains(Data storage self, uint value)
      public
      view
      returns (bool)
  {
      return self.flags[value];
  }
}

contract C {
    using Set for Set.Data; // this is the crucial change
    Set.Data knownValues;

    function register(uint value) public {
        // Here, all variables of type Set.Data have
        // corresponding member functions.
        // The following function call is identical to
        // `Set.insert(knownValues, value)`
        require(knownValues.insert(value));
    }
}

我们也可以通过这种方式来扩展基本类型。

pragma solidity ^0.4.16;

library Search {
    function indexOf(uint[] storage self, uint value)
        public
        view
        returns (uint)
    {
        for (uint i = 0; i < self.length; i++)
            if (self[i] == value) return i;
        return uint(-1);
    }
}

contract C {
    using Search for uint[];
    uint[] data;

    function append(uint value) public {
        data.push(value);
    }

    function replace(uint _old, uint _new) public {
        // This performs the library function call
        uint index = data.indexOf(_old);
        if (index == uint(-1))
            data.push(_new);
        else
            data[index] = _new;
    }
}
需要注意的是所有库调用都实际上是EVM函数调用。这意味着,如果你传的是memory类型的,或者是值类型,那么仅会传一份拷贝,即使是self变量。变通之法就是使用存储类型的变量,这样就不会拷贝内容。


Solidity是用于编写智能合约的编程语言,在区块链开发中应用广泛,而Web.js(如web3.js)则是用于与区块链进行交互的JavaScript库,二者在区块链前端开发中紧密相关。 在岗位方面,Solidity开发主要负责智能合约的开发,从业者除了要了解相关的Solidity语法知识,还需要接触各种dapp,该岗位在上海、深圳、北京较多,其他省份基本没有;而web3.js开发与传统的web2前端开发工程师类似,学习基础的前端知识,多了解一个web3的库即可,主要开发前端js代码,通过js进行合约交互和绘制合约界面,EVM开发岗位较多,需要了解EVM底层原理 [^1]。 从技术应用层面看,对于前端开发者而言,Web2应用的开发主要依赖于传统的Web技术,如HTML、CSS、JavaScript等;而Web3应用的开发,如涉及Solidity应用前端,需要掌握更多的区块链技术、去中心化技术以及智能合约编程等方面的知识,同时也需要更加注重用户隐私和安全等方面的考虑 [^3]。 在使用web3.js与Solidity合约交互时,web3可通过contract调用部署的合约,这里的合约通常是用Solidity语言编写的。web3本身也有一些api可以直接和区块链交互。不过,不同区块链上即便为同一种代币,也是不互相关联的,可看成是两个数据库的数据。并且不同版本的web3方法可能不一样,文档有些又不全,需要类比和阅读源码,多次测试 [^2]。 以一个web3博客系统为例,其涉及的技术栈包括Next.js、Polygon、Solidity、The Graph、IPFS、Hardhat等,其中Hardhat是Ethereum开发环境,web3modal可方便快速地连接钱包等 [^4]。 以下是一个简单的使用web3.js调用Solidity合约的示例代码: ```javascript const Web3 = require('web3'); // 假设已经部署的合约地址和ABI const contractAddress = 'YOUR_CONTRACT_ADDRESS'; const contractABI = [/* 合约ABI */]; // 初始化web3实例 const web3 = new Web3('YOUR_PROVIDER_URL'); // 获取合约实例 const contract = new web3.eth.Contract(contractABI, contractAddress); // 调用合约的某个方法 contract.methods.someFunction().call() .then(result => { console.log('合约方法调用结果:', result); }) .catch(error => { console.error('调用合约方法时出错:', error); }); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值