前言
Dart是面向对象的编程语言,这里函数也可以对象,并且有自己的类型,Function. Function可以作为参数也可以作为返回值。
我们声明一个函数的方式
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
我们可以忽略返回值,因为编译器可以推断返回值
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
如果函数体里面只有一行代码,我们可以使用箭头表达式,如下:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
关于参数
函数可以传递参数,这里有两种参数可以使用,一种是命名参数,另外一种是可选位置参数.
命名参数
命名参数我们可以定义为必须和非必需,区别就是是否使用required标记。当定义一个可选的命名参数如果没有
required标记,并且没有提供默认的值,我们必须要标记该参数为可Null类型。
void enableFlags({bool? bold, bool? hidden}) {...}
在调用该函数时候我们可以指定赋值参数的名字,例如
enableFlags(bold: true, hidden: false);
我们可以提供默认值给参数
void enableFlags({bool bold = false, bool hidden = false}) {...}
在调用方法时候,因为有了默认值,我们不指定参数的值也是可以的
void enableFlags({bool bold = false, bool hidden = false}) {...}
enableFlags(bold: true);
之前有提到过一个required关键字,用于指定必须要提供的参数
const Scrollbar({super.key, required Widget child});
这种情况下调用Scrollbar必须要传child,否则编译器会报错.
required标记的参数也可以为nullable.
const Scrollbar({super.key, required Widget? child});
命名参数可以任意调换位置,只要赋值的时候给定参数名即可
可选位置参数
这里所谓可选位置参数,是我们在调用方法时候必须按照顺序提供参数,但是一部分后面的参数可以选择不传。
例如
String say(String from, String msg, [String? device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
这里我们调用该方法可以不需要传第三个参数device.
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
也可以传第三个参数
assert(say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal');
我们也可以给device赋默认值
String say(String from, String msg, [String device = 'carrier pigeon']) {
var result = '$from says $msg with a $device';
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon');
这里要注意的是默认值必须要是常量.
函数作为对象
函数可以作为对象进行传参
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// printElement作为一个参数传递给forEach.
list.forEach(printElement);
你也可以赋值一个函数给一个变量.
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
匿名函数
通常函数都会有名字,不过没有函数名字的函数称为匿名函数,大致格式如下
([[*Type*] *param1*[, …]]) {
*codeBlock*;
};
这里,我们也能定义参数和返回值。
const list = ['apples', 'bananas', 'oranges'];
list.map((item) {
return item.toUpperCase();
}).forEach((item) {
print('$item: ${item.length}');
});
在map和forEach函数中传入的都称为匿名函数,如果函数体里面只有一行代码我们可以使用箭头操作符简化操作
list
.map((item) => item.toUpperCase())
.forEach((item) => print('$item: ${item.length}'));
词法范围
变量的作用返回都在大括号的范围内,自内向外访问,不能外层访问内层的变量。
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
例如myFunction是不能访问insideNestedFunction,因为insideNestedFunction在nestedFunction中声明。
函数的返回值
函数的返回值可以隐式推断,例如
foo() {}
assert(foo() == null);
foo 并没有声名返回值,但是编译器推断它返回null.