函数(Function Types)
函数类型1即是函数这种特殊的类型。
- 可以将一个函数赋值给一个变量,一个函数类型的变量。
- 还可以将一个函数作为参数进行传递。
- 也可以在函数调用中返回一个函数。
函数类型有两类;可分为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字节的函数方法签名2的共占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 < 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
函数明明是两个参数,但只需要传一个呢。
-
http://solidity.readthedocs.io/en/develop/types.html#function-types ↩
-
函数签名的编码方式可查看函数选择器相关章节,【文档翻译系列】ABI详解 ↩
处于某些特定的环境下,可以看到评论框,欢迎留言交流^_^。