函数
在Dart中,函数(或方法) 也是对象,它的类型是
Function。 这意味着,函数可以赋值给变量,也可以当做其他函数的参数。
定义函数
Dart中定义函数,基本上与Java类似
String greet(String name){
return "hello,$name";
}
在Dart中,类型是可选,可以省略显式的类型,但仍然建议显式指定类型。
greet(name){
return "hello,$name";
}
要注意,函数也是对象,所有函数都有返回值。当没有指定返回值的时候,函数会返回null。当然,如果你强行使用void来修饰函数,则函数真的没有返回值,这种情况就另当别论了。
函数的参数
Dart中支持两种可选参数
- 命名可选参数
- 位置可选参数
在Java中通常使用方法重载来实现同名方法的不同参数调用,Dart中则可以通过可选参数来实现相同效果。
命名可选参数
先来看一下命名参数,它使用花括号来定义参数列表
// 定义一个函数,参数列表用花括号包裹
enableFlags({bool bold, bool hidden}) {
// do something
}
// 调用方式,传参时使用"参数名:值"的形式
enableFlags(hidden:true,bold:false);
如果在定义函数时,给参数列表中的参数设置默认值,则该参数就是可选的,函数调用时可以忽略该参数,使用默认的值。
// 定义add函数
add({int x, int y=1, int z=0}){
print(x + y + z;
}
// 调用
add(x:18); // 19
add(x:18, y:2, z:10); // 30
这里需要注意一下,SDK 1.21之前的版本中,命名参数不能使用=号来设置默认值,而SDK 1.21之后,只能使用=号来设置默认值。因此,请检查并升级SDK版本。
位置可选参数
位置可选参数使用中括号来定义参数列表,中括号中的参数是可选的
// 定义add函数
add(int x, [int y, int z]){
int result = x;
if (y != null){
result = result + y;
}
if (z != null){
result = result + z;
}
print(result);
}
// 调用
add(18); // 18
add(18,12); // 30
add(18, 12, 15); // 45
给位置可选参数设置默认值
// 定义add函数
add(int x, [int y=0, int z=0]){
print(x +y+z);
}
最后需要注意一下命名可选参数与位置可选参数的区别,前者中的参数与顺序无关,无需按顺序传参,且传参数时需使用冒号;后者与顺序相关,传参必须依照顺序。
匿名函数
大部分函数都有名字,但我们也可以创建没有名字的函数,称为匿名函数,也被称为lambda表达式或者闭包。
// 定义匿名函数,并将其赋值给一个变量func,注意,函数体最后的花括号处必须有分号结束。
var func = (x,y){
return x + y;
};
print(func(10,11)); // 21
注意,匿名函数与普通函数基本相同,也有参数列表,函数体,只是省去了函数名而已。
箭头函数
Dart中的箭头函数与JavaScript中的基本相同。当函数体中只包含一个语句时,我们就可以使用
=>箭头语法进行缩写。注意,箭头函数仅仅只是一个简洁表达的语法糖。
普通函数
add(num x, num y){
return x + y;
}
print(add(18,12)); // 30
箭头函数
// 与上面的普通函数完全等价
add(num x, num y) => x + y;
print(add(18,12)); // 30
箭头函数省略了花括号的表达,箭头后面跟一个表达式,函数的返回值也就是这个表达式的值。另外,箭头函数也可以与匿名函数结合,形成匿名箭头函数。
var func = (num x, num y) => x + y;
函数类型与函数签名
void func(Function f,String content){
// 调用f函数
f(content);
}
void main() {
// 函数本身也是一种类型,可使用Function声明函数类型变量
Function f = (String text){
print(text);
};
// 将函数作为参数传递
func(f, "编程之路");
}
如上例,我们可以声明函数类型变量,并将函数作为参数传递,但很快我们就会发现这样使用的弊端
void main() {
// 当我们传入一个与参数不匹配的函数时,语法检查不会报错,但运行时会报错
func((int a,int b){
return a+b;
}, "编程之路");
}
直接使用Function类型来声明函数变量做形式参数,是无法检查该函数的形式参数的,而且这样代码可读性太差,我们无法获知该函数变量的形式参数声明信息。这时候,就需要使用关键字typedef来定义函数的签名。
// 定义一个函数签名:表示F函数的原型为 void F(String)
// 其中F表示该函数类型的别名
typedef void F(String);
// 使用F类型来声明形参 f
void func(F f,String content){
f(content);
}
void main() {
// 此时再传入一个签名不匹配的函数,语法检查直接报错
func((int a,int b){
return a+b;
},
}
使用typedef来定义函数的签名通常有两种写法,一种如上例,typedef后面直接跟函数的签名,另一种可读性更好,推荐使用
// 公式:typedef 函数类型别名 = 函数签名
typedef F = void Function(String);
公众号“编程之路从0到1”