🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 函数(Function Types) 函数类型即是函数这种特殊的类型。 - 可以将一个函数赋值给一个变量,一个函数类型的变量。 - 还可以将一个函数作为参数进行传递。 - 也可以在函数调用中返回一个函数。 函数类型有两类;可分为`internal`和`external`函数。 ## 内部函数(internal) 因为不能在当前合约的上下文环境以外的地方执行,内部函数只能在当前合约内被使用。如在当前的代码块内,包括内部库函数,和继承的函数中。 ## 外部函数(External) 外部函数由地址和函数方法签名两部分组成。可作为`外部函数调用`的参数,或者由`外部函数调用`返回。 ## 函数的定义 完整的函数的定义如下: ``` function (<parameter types>) {internal(默认)|external} [constant] [payable] [returns (<return types>)] ``` 若不写类型,默认的函数类型是`internal`的。如果函数没有返回结果,则必须省略`returns`关键字。下面我们通过一个例子来了解一下。 ``` pragma solidity ^0.4.0; contract Test{ //默认是internal类型的 function noParameter() returns (uint){} //无返回结果 function noReturn1(uint x) {} //如果无返回结果,必须省略`returns`关键字 //function noReturn2(uint x) returns {} } ``` 如果一个函数变量没有初始化,直接调用它将会产生异常。如果`delete`了一个函数后调用,也会发生同样的异常。 如果`外部函数`类型在`Solidity`的上下文环境以外的地方使用,他们会被视为`function`类型。编码为20字节的函数所在地址,紧跟4字节的函数方法签名的共占24字节的`bytes24`类型。 合约中的`public`的函数,可以使用`internal`和`external`两种方式来调用。下面来看看,两种方式的不同之处。 ## 函数的`internal`与`external`: 调用一个函数`f()`时,我们可以直接调用`f()`,或者使用`this.f()`。但两者有一个区别。前者是通过`internal`的方式在调用,而后者是通过`external`的方式在调用。请注意,这里关于`this`的使用与大多数语言相背。下面通过一个例子来了解他们的不同: ``` pragma solidity ^0.4.5; contract FuntionTest{ function internalFunc() internal{} function externalFunc() external{} function callFunc(){ //直接使用内部的方式调用 internalFunc(); //不能在内部调用一个外部函数,会报编译错误。 //Error: Undeclared identifier. //externalFunc(); //不能通过`external`的方式调用一个`internal` //Member "internalFunc" not found or not visible after argument-dependent lookup in contract FuntionTest //this.internalFunc(); //使用`this`以`external`的方式调用一个外部函数 this.externalFunc(); } } contract FunctionTest1{ function externalCall(FuntionTest ft){ //调用另一个合约的外部函数 ft.externalFunc(); //不能调用另一个合约的内部函数 //Error: Member "internalFunc" not found or not visible after argument-dependent lookup in contract FuntionTest //ft.internalFunc(); } } ``` ## 函数例子(官方) ``` pragma solidity ^0.4.0; library ArrayUtils{ function range(uint length) internal returns (uint[] memory r){ r = new uint[](length); for(uint i = 0; i < length; i++){ r[i] = i; } } function map(uint[] memory self, function(uint) returns (uint) f ) internal returns (uint[] memory r) { r = new uint[](self.length); for(uint i = 0; i &lt; self.length; i++){ r[i] = f(self[i]); } } function reduce(uint[] memory self, function(uint x, uint y) returns(uint) f ) internal returns (uint r) { r = self[0]; for(uint i = 1; i < self.length; i++){ r = f(r, self[i]); } } } contract Pyramid{ using ArrayUtils for *; function pryamid(uint length) returns (uint){ return ArrayUtils.range(length).map(square).reduce(sum); } function square(uint x) returns (uint){ return x * x; } function sum(uint x, uint y) returns (uint){ return x + y; } } ``` Question? - `library`是什么呢。 - `library`引入时为什么使用`using`,这和文件引入的`import`有何区别。 - `library`内的函数全是`internal`的。 - `library`内的函数,他的参数函数为什么是`internal`的,不应该是`external`的? - `uint[]`是什么类型,不能写做`[]uint` - `memory`又是什么呢,为什么`map`函数明明是两个参数,但只需要传一个呢。