library

1)直接使用
使用库合约的合约,可以将库合约视为隐式的父合约(base contracts),当然它们不会显式的出现在继承关系中。意思就是不用写is来继承,直接可以在合约中使用:

library Set {
struct Data { mapping(uint => bool) flags; }
} contract C {
Set.Data knownValues;
}

但调用库函数的方式非常类似,如库L有函数f(),使用L.f()即可访问。此外,internal的库函数对所有合约可见,如果把库想像成一个父合约就能说得通了。当然调用内部函数使用的是internal的调用惯例,这意味着所有internal类型可以传进去,memory类型则通过引用传递,而不是拷贝的方式。

library Set {
// We define a new struct datatype that will be used to
// hold its data in the calling contract.
struct Data { mapping(uint => bool) flags; } // Note that the first parameter is of type "storage
// reference" and thus only its storage address and not
// its contents is passed as part of the call. (意思是说这是个引用传递) This is a
// special feature of library functions. It is idiomatic(就是惯例都把第一个变量命名为self,当然你也可以命名为其他的)
// to call the first parameter 'self', if the function can
// be seen as a method of that object.
function insert(Data storage self, uint value)
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
} function remove(Data storage self, uint value)
returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
} function contains(Data storage self, uint value)
returns (bool)
{
return self.flags[value];
}
} contract C {
Set.Data knownValues; function register(uint value) {
// The library functions can be called without a
// specific instance of the library, since the
// "instance" will be the current contract.
if (!Set.insert(knownValues, value))
throw;
}
// In this contract, we can also directly access knownValues.flags, if we want.
}

上面的例子中:
  
 •    Library定义了一个数据结构体struct
Data,用来在调用的合约中使用(库本身并未实际存储的数据)。如果函数需要操作数据,这个数据一般是通过库函数的第一个参数传入(Data
storage self),按惯例会把参数名定为self。
    •    另外一个需要留意的是上例中self的类型是storage,那么意味着传入的会是一个引用,而不是拷贝的值,那么修改它的值,会同步影响到其它地方,俗称引用传递,非值传递。
    •    库函数的使用不需要实例化,c.register函数中可以看出是直接使用Set.insert。但实际上当前的这个合约本身就是它的一个实例。
    •    这个例子中,c可以直接访问knownValues。虽然这个值主要是被库函数使用的

对比普通合约来说,库的限制:
    •    无状态变量(state variables)。
    •    不能继承或被继承
    •    不能接收ether。

2)通过附着库(Using for)来使用库
指令using A for B;用来附着库里定义的函数(从库A)到任意类型B。这些函数将会默认接收调用函数对象的实例作为第一个参数。语法类似,python中的self变量一样。
using A for *的效果是,库A中的函数被附着在做任意的类型上。
在这两种情形中,所有函数,即使那些第一个参数的类型与调用函数的对象类型不匹配的,也被附着上了。类型检查是在函数被真正调用时,函数重载检查也会执行。
using
A for
B;指令仅在当前的作用域有效,且暂时仅仅支持当前的合约这个作用域,后续也非常有可能解除这个限制,允许作用到全局范围。如果能作用到全局范围,通过引入一些模块(module),数据类型将能通过库函数扩展功能,而不需要每个地方都得写一遍类似的代码了。
上面的例子就改成了:

contract C {
using Set for Set.Data; // this is the crucial change
Set.Data knownValues; function register(uint value) {
// Here, all variables of type Set.Data have
// corresponding member functions.
// The following function call is identical to
// Set.insert(knownValues, value)
if (!knownValues.insert(value))
throw;
}
}

//其实就是本来要访问的话的语句是Set.insert(knownValues,
value),现在是knownValues.insert(value),即将库中的函数都附着在了结构体struct
Data上,因为之前库函数的第一个参数self的声明其实也是这个结构体(Data),附着后调用时就可以省略掉第一个参数了,因为它默认接收调用函数对象的实例作为第一个参数。就算库中没有结构体,那么附着的一定是函数的第一个参数声明的那个self的类型,如string、uint[]等,如下面的例子:

library Search {
function indexOf(uint[] storage self, uint value) contract C {
using Search for uint[];
uint[] data;
//这样调用就可以变成:
data.indexOf(value);

solidity-library的更多相关文章

  1. Solidity: ParserError: Expected pragma, import directive or contract/interface/library definition.

    第一行忘记加分号 pragma solidity ^0.4.0;

  2. solidity 学习笔记(4)library库

    library库的申明: library SafeMath{ functrion mul(uint a,uint b) public returns (uint){ uint c= a*b; asse ...

  3. 智能合约语言 Solidity 教程系列3 - 函数类型

    Solidity 教程系列第三篇 - Solidity 函数类型介绍. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以 ...

  4. Solidity 中文文档 —— 第一章:Introduction to Smart Contracts

    第一章:智能合约简介 粗略地翻译了 Ethereum 的智能合约开发语言的文档:Solidity.欢迎转载,注明出处. 有任何问题请联系我,本人微信:wx1076869692,更多详情见文末. 我是 ...

  5. Solidity知识点集 — 溢出和下溢

    合约安全增强: 溢出和下溢 什么是 溢出 (overflow)? 假设我们有一个 uint8, 只能存储8 bit数据.这意味着我们能存储的最大数字就是二进制 11111111 (或者说十进制的 2^ ...

  6. solidity learning (1)

    学习文档笔记:http://solidity-cn.readthedocs.io/zh/develop/layout-of-source-files.html 1.pragma solidity ^0 ...

  7. solidity学习-cryptoPunks为实例

    在这里使用cryptoPunks为实例来进行solidity的介绍,一般这些内容理解了就能够进行相对简单的智能合约的编写了,同时会添加一些我认为也十分重要的内容学习文档为http://solidity ...

  8. solidity 汇编语言问题——内存数据mload时为什么从第32位开始

    问题:内存数据mload时为什么从第32位开始 代码出处:https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d pragma so ...

  9. Solidity之mapping类型

    映射是一种引用类型,存储键值对.它的定义是:mapping(key => value),概念上与java中的map,python中的字典类型类似,但在使用上有比较多的限制. 一.mapping定 ...

  10. etherlime-2-Etherlime Library API-deployer

    Etherlime Library API 库API Deployer部署者 Deployer functionality The main functionality the deployer ex ...

随机推荐

  1. MVC 的 Razor引擎显示代码表达式与隐式代码表达式

    隐式代码表达式 就是一个标识符,之后可以跟任意数量的方法调用("()").索引表达式("[]")及成员访问表达式(".").但是,除了在&q ...

  2. C# 循环语句 for

    循环:反复执行某段代码. 循环四要素:初始条件,循环条件,循环体,状态改变. for格式 for(初始条件;循环条件;状态改变) { 循环体 } break ——中断循环,跳出整个循环 continu ...

  3. (2)Microsoft office Word 2013版本操作入门_快速选中

    1.快速选中一行 .一段文字: 1.1光标在一行内,双击会选中一个词组.快速点击三下会选中一段, 1.2 鼠标移动到行首,单击击会选中一行,双击选中一段. 1.3 选择全部内容 Ctrl+A  , 1 ...

  4. 【Mybatis】1、Mybatis拦截器学习资料汇总

    MyBatis拦截器原理探究 http://www.cnblogs.com/fangjian0423/p/mybatis-interceptor.html [myBatis]Mybatis中的拦截器 ...

  5. Python 练习: 计算器

    import re def format_string(s): # 对表达式进行格式化 s = s.replace(' ', '') s = s.replace("--", &qu ...

  6. Navicat安装及简单使用

    一.安装 下载完之后,直接解压出来就能用,看一下解压之后的目录: 双击打开下面这个文件(可以把它添加一个桌面快捷方式,或者添加到任务栏): 然后会提示你输入注册码: 回到navicat的解压出来的文件 ...

  7. 1788:Pell数列

    1788:Pell数列 查看 提交 统计 提问 总时间限制:  3000ms 内存限制:  65536kB 描述 Pell数列a1, a2, a3, ...的定义是这样的,a1 = 1, a2 = 2 ...

  8. React报错:Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix,

    今天在开发时报了以下错误,记录一下 我们不能在组件销毁后设置state,防止出现内存泄漏的情况 出现原因直接告诉你了,组件都被销毁了,还设置个锤子的state啊 解决方案: 利用生命周期钩子函数:co ...

  9. css选择器:基本选择器

    基本选择器 1.通用元素选择器 *表示应用到所有的标签. *{ padding:0px; margin:0px; } 2.元素/标签选择器 匹配所有p标签的元素 p{ color:red; backg ...

  10. Ubuntu 18 + Redis安装

    Ubuntu 18 + Redis安装 1.安装命令: opengis@gisserver20:~$ sudo apt-get install redis-server 2.查看tcp 连接 open ...