1,函数的定义
返回值 函数的名称(参数列表) {
函数体
return 返回值
}
按照上面的格式定义一个简单的计算两个数字相加:
num sum(num a, num b) {
return a + b;
}
函数的参数和返回值类型也可以省略,这样这个函数可以计算所有支持+运算的处理,并自动推导对应的类型:
print(sum("abc", "def").runtimeType); // String
print(sum(1, 2).runtimeType); // int
print(sum(1, 2.0).runtimeType); // double
print(sum(1.0, 2.0).runtimeType); // double
print(sum([1, 2, 3], [4, 5, 6]).runtimeType); // List<int>
sum(a, b) {
return a + b;
}
但函数体中,只有一行表达式的时候,可以使用箭头语法,上面的sum函数可以写成:
sum(a, b) => a + b;
所有的函数的都有返回值,如果没有返回值,默认返回null。
2,可选参数
实现可选参数,可以使用两种方式:
命名可选参数: {param1, param2, ...}
位置可选参数: [param1, param2, ...]
1,命名可选参数
printInfo1("Jack", height: 1.88, age: 18);
void printInfo1(String name, {int age, double height}) {
print("name: $name, age: $age, height: $height");
}
命名可选参数将可选参数统一用{}扩起来,定义在必传参数后面,当函数调用时,先传入必传参数,再通过 别名: 参数值 的格式传入参数。因为通过参数别名来传递,所以命名可选参数不需要按照函数声明的顺序传递。 Flutter中的组件都是通过这种命名可选参数进行传值,例如:
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
debugShowCheckedModeBanner: false,
);
}
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
MaterialApp中的初始化方法中,home和debugShowCheckedModeBanner参数的传入顺序可以变化,通过查看源码可以看到,所有的参数都是使用{}扩起来,定义为命名可选参数:
const MaterialApp({
Key key,
this.navigatorKey,
this.home,
this.routes = const <String, WidgetBuilder>{},
this.initialRoute,
...
})
在Flutter开发环境中,还可以对命名可选参数添加@required关键字,让对应的命名可选参数变成必传参数:
void printInfo1(
String name,
{
@required int age,
double height,
}) {
print("name: $name, age: $age, height: $height");
}
之所以这样做,因为dart中,默认的必传参数是没有别名并且必须按照声明顺序传递,而通过命名可选参数加@required关键字,就可以实现带参数别名、不限制顺序并且必传的需求。Flutter中大量采用这种参数的声明方式,比如RaisedButton的初始化方法中,onPressed参数的声明:
const RaisedButton({
Key key,
@required VoidCallback onPressed,
VoidCallback onLongPress,
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme,
...
})
2,位置可选参数
位置可选参数在传入参数时,没有参数别名,必须按照对应的位置来传递:
void printInfo2(String name, [int age, double height]) {
print('name=$name age=$age height=$height');
}
3,参数默认值
只有可选参数才可以设置默认值:
void printInfo1(String name, {int age = 0, double height = 1.7}) {
print('name=$name age=$age height=$height');
}
3,函数是一等公民
在iOS开发中,Objective-C不同于Swift中的一点,就是它不支持将函数作为一等公民来使用,函数不能作为变量和参数、和返回值使用。Dart支持这一特性。
1,函数赋值给变量
var sunFunc = sum;
print(sunFunc(1, 2));
sum(a, b) => a + b;
2,函数作为参数
如下格式,创建一个函数,传入两个int类型值,和一个传入两个int类型参数返回一个int类型的函数。在函数体中,调用传入的函数,并前两个参数传入,并返回最终值:
int test(int a, int b, int f(int e1, int e2)) {
return f(a, b);
}
下面可以将函数做为参数传入,当函数作为参数时,只需要写函数名:
print(test(3, 4, sum)); // 7
print(test(5, 3, sub)); // 2
int sum(int a, int b) => a + b;
int sub(int a, int b) => a - b;
int test(int a, int b, int f(int e1, int e2)) {
return f(a, b);
}
3,匿名函数
还是上面定义的函数:
int test(int a, int b, int f(int e1, int e2)) {
return f(a, b);
}
上面都是通过传入一个定义好的函数的函数名来实现,下面可以通过匿名函数的方式来实现:
print(test(2, 3, (a, b){
return a * b;
})); // 6
如果要传入的函数只有一个表达式,可以用箭头表达式简写:
print(test(2, 3, (a, b) => a * b)); // 6
匿名函数在Flutter开发中,很多地方都有用到,比如List的遍历:
List<int> list = [1, 2, 3];
list.forEach((element) => print(element));
或者Flutter开发中,RaisedButton的onPressed:
RaisedButton(
child: Text("+", style: TextStyle(fontSize: 20, color: Colors.white),),
color: Colors.pink,
onPressed: (){
print("+ pressed");
},
),
4,词法闭包
闭包可以访问其词法范围内的变量,即使函数在其他地方被使用,也可以正常的访问。
main(List<String> args) {
makeAdder(num addBy) {
return (num i) {
return i + addBy;
};
}
var adder2 = makeAdder(2);
print(adder2(10)); // 12
print(adder2(6)); // 8
var adder5 = makeAdder(5);
print(adder5(10)); // 15
print(adder5(6)); // 11
}