solidity-library

librarypython

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类型则经过引用传递,而不是拷贝的方式。app

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。ide

 


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[]等,以下面的例子:ui

library Search { function indexOf(uint[] storage self, uint value) contract C { using Search for uint[]; uint[] data;    //这样调用就能够变成:    data.indexOf(value);
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息