2.6 函数 – 《简单易懂的Dart》

2.6.1 第一类函数

第一类函数数就是Dart中的lambda表达式,只有一条语句.

这种形式的函数我们在2.4.3 for each循环中已经接触过.

第一类函数由2部分组成,分别是参数部分和返回部分.

我们来看一个简单的第一类函数:

(int i) => i+1

其中(int i)是其参数部分,用于接收参数.

i+1是其返回部分,用于决定返回值.

这里定义了一个int类型的变量i,并将i+1的结果返回给函数的调用者.

由于第一类函数没有函数名,我们也可以称之为匿名函数.

下面是一个简单的调用上面代码的例子:

void main(){  
  print(((int i)=>i+1)(100));
}

输出结果为101,来分析一下它的执行顺序.

首先,((int i) => i+1)使它成为了一个第一类函数,最外层的()将其作为一个对象(这里是函数对象)来对待,后面(100)则是将100作为参数传进函数.

然后,值100进入了函数,100是一个整型值,它通过了int i的类型检查,根据表达式i+1将执行100+1的操作.

最后,100+1=101作为返回值返回,print受到参数并打印出101.

2.6.2 标准函数

标准函数是我们喜闻乐见的C类语言照搬版本.

格式如下:

返回值类型 函数名(参数表){
  函数体
  return 返回值
}

上面那个第一类函数的例子也可以写成标准函数:

void main(){  
  int plus1(int i){
    return i+1;
  }
  print(plus1(100));
}

这里需要注意的是,返回值与其返回值类型必须一致,否则将会出错.

但是这样又有了返回值的局限性,Dart就这么的不好用吗?

当然不是,其实标准函数的返回值类型是可以省略的!

void main(){  
  plus1(int i){
    return i+1;
  }
  print(plus1(100));
}

因为这个特性,所以这段代码可以正常执行.

2.6.3 可省参数

Dart支持可省参数,增强了一定的灵活性.

可省参数需要遵循2个规范:可省参数位于函数表的最后,可省参数必须被包括在[]中.

我们将上面的plus1函数加以强化,使它在接收到第二个参数时可以变为两个参数相加.

void main(){  
  plus1(int i,[int j]){
    if(j!=null){
      return i+j;
    }else{
      return i+1;
    }
  }
  print(plus1(100));
  print(plus1(100,200));
}

输出结果为

101  
300  

如果可省参数被省略,则其值为null,我们可以依靠这个特性编写if(j!=null)来判断参数是否省略.

由于return后不会继续执行下面的代码,这段代码还可以写成这样:

void main(){  
  plus1(int i,[int j]){
    if(j!=null){
      return i+j;
    }
    return i+1;
  }
  print(plus1(100));
  print(plus1(100,200));
}

2.6.4 参数默认值

在上一节学习了可省参数,这里再学习一下可省参数的默认值写法.

给参数设置默认值非常简单,就像定义一个变量并给它赋值一样容易.

上面的例子中j如果不存在则将执行i+1的操作,下面我们把j的默认值设置为1.

这样在参数j被省略时执行i+1,参数j存在时执行i+j.

代码是这样的:

void main(){  
  plus1(int i,[int j=1]){
    return i+j;
  }
  print(plus1(100));
  print(plus1(100,200));
}

plus1(100)时由于参数j被省略,其默认值1使得i+j=i+1=100+1=101.

plus1(100,200)时由于参数j未被省略,其默认值不生效,j=200,使得i+j=i+200=100+200=300.

2.6.5 无类型参数

干脆连参数的类型都不要定义了吧,这多方便啊!

void main(){  
  plus1(i,[j=1]){
    return i+j;
  }
  print(plus1(100));
  print(plus1(100,200));
}

Dart:什么?你说我有点像JavaScript?

2.6.6 函数对象

上面或多或少提到了——函数其实是个对象.

函数对象的类型为Function类型.

所以它是可以被赋值的.像这样:

void main(){  
  plus1(i,[j=1]){
    return i+j;
  }
  Function plus2=plus1;
  print(plus2(100));
  print(plus2(100,200));
}

Function类型变量plus2初始化时给他plus1,此时plus2有了和plus1同样的对象.

返朴归真一下,现在我们把plus1还原成第一类函数吧.

void main(){  
  Function plus1=(i,[j=1])=>i+j;
  print(plus1(100));
  print(plus1(100,200));
}

是不是有一种很高级的感觉?第一类函数同样支持标准函数的种种特性.

我们索性连Function也换成var怎么样?

void main(){  
  var plus1=(i,[j=1])=>i+j;
  print(plus1(100));
  print(plus1(100,200));
}

只需要添加几个字符,原来的那个第一类函数就增加了新功能,并且还进行了命名!