# 函数(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 < 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`函数明明是两个参数,但只需要传一个呢。
- Solidity语言
- 入门说明
- Solidity智能合约文件结构
- 智能合约源文件的基本要素概览
- 值类型
- 类型
- 布尔
- 整型
- 地址
- 字节数组
- 小数
- 字符串
- 十六进制字面量
- 枚举
- 函数
- 引用类型
- 引用类型
- 数据位置
- 数组
- 数据结构
- 杂项
- 映射
- 左值运算符
- 类型间的转换
- 类型推断
- 单位
- 货币单位
- 时间单位
- 语言内置特性
- 特殊变量及函数
- 数学和加密函数
- 地址相关
- 进阶
- 入参和出参
- 控制结构
- 函数调用
- 创建合约实例
- 表达式的执行顺序
- 赋值
- 作用范围和声明
- 异常
- 内联汇编
- 合约详解
- 合约
- 可见性或权限控制
- 访问函数
- 函数修改器
- 常状态变量
- 回退函数
- 事件
- 继承
- 接口
- 其它
- 库
- 状态变量的存储模型
- 内存变量的存局
- 调用数据的布局