一、上初中的时候,数学老师说的函数长这个样子
学生时代,老师告诉我们,函数包含三个部分: 1、函数名 2、参数 3、返回值
二、Flutter的函数定义
Flutter扩展了初中老师的概念,多了一个异步函数和同步函数的东西,异步就是async。 接下来,我们认真来学习一下函数的每个部分
三、函数名(名字是可有可无的)
- 命名函数——顾名思义,就是有名字的函数,例如
void initState() {},initState就是函数名。 - 匿名函数——例如,
() {print('Hello');},这就是一个最简单(没有返回,没有参数)的匿名函数了。 - 为什么要有匿名函数呢?很简单,"如果一个函数只在一个地方被调用,为什么要有个名字呢?"。这种情况在
函数化编程中是司空见惯的
四、函数化编程
所谓函数化编程,就是将一个函数作为另一个函数的参数(或返回值),你看下面的代码,其中 f( (){ print('hello');} );这一行,就是给一个叫做 f 的函数传入一个匿名参数作为参数
//定义一个函数f,参数是一个无参无返回值的函数callback
void f( Function() callback ) {
callback();
}
void main() {
//调用函数f,传入一个匿名函数作为参数,这个匿名函数会打印'hello'
f( (){ print('hello'); });
}
五、异步函数
如果在f()后面添加了"async",那么f就是一个异步函数,异步函数有几个变化
- 假设函数的返回值原来是T,会自动变成了
Future<T>,意思是"如果调用该函数,会立刻返回一个未来的T"
f1(){
return "hello world";
}
f2() async{
return "hello world";
}
void main() {
print( f1() );
print( f2() );
/*
输出结果
hello world
Instance of 'Future<dynamic>'
*/
}
你如果如下这么定义f2,就会编译不过
String f2() async{ return "hello world";}
正确完整的写法是:
Future<String> f2() async{return "hello world";}
- 在异步函数内部,可以使用await,普通函数内部不能使用await。
f1() async{
print("come 1");
}
void main() async{
await f1();
...
//async+await这种方式,其实是将异步的实现,模拟成同步的方式给你看
//感觉是1个线程停下来,等待另一个线程先执行,事实上,在异步的世界里面根本就没有多线程,也根本就没有等待这回事。
}
- 在异步函数外部,支持
.then()/.catchError()/.whenComplete()等链式调用
f1() async{
print("come 1");
}
void main() {
f1().then( (_){print ("come 2");} );
print("come 3");
}
/*
输出的结果如下:
come 1
come 3
come 2
*/
六、Dart语言是面向对象的,但是不支持函数重载,只支持函数覆盖
也就是说不能有同名的函数
class A{
f1(String s) {
print("come $s");
}
f1(String s, int i) {//编译不过,不能有两个叫做f1的函数,这一点和Java和C++等面向对象语言完全不一样
print("come $i");
}
}
这是因为Dart有更加牛的实现方式——可选参数
class A{
f1(String s,[int? i]) {
print("$s $i");
}
}
void main() {
A().f1('hello');
A().f1('hello',3);
}
/*
输出:
hello null
hello 3
*/
七、其他
- Dart函数的参数,除了顺序传递之外,还能通过命名参数的方式传递,比如
class A{
f1({required String s, int? i}) {
print("$s $i");
}
}
void main() {
A().f1( s:'hello' );
A().f1( s:"hello", i : 5 );
}
- 以下划线开头的函数,是私有函数,就类似Java/C++里面的private
说了这么多,大家自己试一试呗,如果是完全没有经验的开发者,建议先看看Flutter起步教程,网址 docs.flutter.cn/get-started