一、函数
1、 函数的基本定义
Dart是一种真正的面向对象语言,所以即使函数也是对象, 类型就是Function。这也就意味着函数可以作为变量定义或者作为其他函数的参数或者返回值。
函数的定义方式:
返回值 函数的名称(参数列表) {
函数体
return 返回值
}
按照上面的定义方式, 我们定义一个完整的 求和 函数:
int sum(int num1, int num2) {
return num1 + num2;
}
- 提示一:Effective Dart建议对公共的API, 使用类型注解, 但是如果我们省略掉了类型, 依然是可以正常工作的
sum(num1, num2) { return num1 + num2; }
- 提示二:如果函数中只有一个表达式, 那么可以使用箭头语法(arrow syntax),注意, 这里面只能是一个表达式, 不能是一个语句
sum(num1, num2) => num1 + num2;
2、函数的参数问题:必须参数和可选参数
- 必选参数:必须传
void sayHello(String name) {
print(name)
}
// 调用的时候必须传 name
sayHello('Hello Flutter')
可选参数(dart中没有函数重载,也就是函数的名字不能重复) 只有可选参数才可以有默认值
位置可选参数 [int age, double height],实参和形参在进行匹配时,是根据位置的匹配,有顺序的
void sayHello(String name, [int age, double height = 3]) {
print("名字:$name 年龄:$age 身高:$height");
}
// 调用
sayHello("小明");
sayHello("小明", 20);
sayHello("小明", 20, 189.00);
- 命名可选参数: 可以没有顺序
void sayHello(String name, {int age, double height = 3}) {
print("名字:$name 年龄:$age 身高:$height");
}
// 调用
sayHello("小红");
sayHello("小红", age: 20);
sayHello("小红", height: 1.89);
sayHello("小红", age: 20, height: 1.78);
提示: 命名可选参数, 可以指定某个参数是必传的(使用@required, 有问题)
sayHello(String name, {int age, double height, @required String address}) { print('name=$name age=$age height=$height address=$address'); }
3、函数是一等公民
在很多语言中, 函数并不能作为一等公民来使用, 比如Java、OC. 这种限制让编程不够灵活, 所以现代的编程语言基本都支持函数作为一等公民来使用, Dart也支持.
这就意味着你可以将函数赋值给一个变量, 也可以将函数作为另外一个函数的参数或者返回值来使用.
main(List<String> args) {
// 1.将函数赋值给一个变量
var bar = foo;
print(bar);
// 2.将函数作为另一个函数的参数
test(foo);
// 3.将函数作为另一个函数的返回值
var func =getFunc();
func('kobe');
}
// 1.定义一个函数
foo(String name) {
print('传入的name:$name');
}
// 2.将函数作为另外一个函数的参数
test(Function func) {
func('coderwhy');
}
// 3.将函数作为另一个函数的返回值
getFunc() {
return foo;
}
4、匿名函数 和 箭头 函数的使用
匿名函数:大部分我们定义的函数都会有自己的名字, 比如前面定义的foo、test函数等等。
但是某些情况下,给函数命名太麻烦了,我们可以使用没有名字的函数,这种函数可以被称之为匿名函数( anonymous function),也可以叫lambda或者closure。
main(List<String> args) {
test(() {
print("匿名函数的打印");
});
}
test(Function foo) {
foo();
}
- 提示:匿名函数作为参数传递
匿名函数格式:(参数列表) {函数体};
箭头函数:条件:函数体只有一个函数的参数
test(() => print("箭头函数的打印"));
5、词法作用域
dart中的词法有自己明确的作用域范围,它是根据代码的结构({})来决定作用域范围的
优先使用自己作用域中的变量,如果没有找到,则一层层向外查找
var name = 'global';
main(List<String> args) {
// var name = 'main';
void foo() {
// var name = 'foo';
print(name);
}
foo();
}
6、词法闭包
闭包可以访问其词法范围内的变量,即使函数在其他地方被使用,也可以正常的访问。
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
}
提示:makeAdder 是一个函数,返回的也是一个匿名函数,我们再调用和这个匿名函数
7、返回值问题
- 所有的函数都会有返回值。
- 如果没有指定函数返回值,则默认的返回值是 null。
- 如果没有返回值的函数,系统会在最后添加隐式的 return 语句。
main(List<String> args) {
print(foo()); // null
}
foo() {
print('foo function');
}