函数签名
Dart采用与Java一样的函数签名写法
String greet(String name) {
return "Hello, $name";
}
Dart可以通过类型推导确定返回值类型,随意允许在签名中省略返回值类型:
greet(String name) {
return "Hello, $name";
}
个人不推荐省略返回值类型的写法,函数定义和函数调用变得不容易区分影响可读性。
函数是一等公民
Dart中万物皆对象,函数本质上也是Function
类型的实例,类似于Kotlin中也有对应的FunctionN
类型,都继承自kotlin.jvm.functions.Function
接口。 可以将函数像作为一个实例进行参数传递。
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
lambda传参
像Kotlin一样,可以将lambda赋值给函数类型参数
var l = [1,2,3];
l.forEach((i) { print(i); });
lambda内只有一行时,可以使用箭头函数:
l.forEach((i) => print(i));
() => exp
相当于 () { return exp; }
的语法糖,lambda表达式以外,在函数体只有一行的函数声明时也可以使用
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
可选参数(Optional parameter)
Dart的函数参数分为必选参数和可选参数,可选参数在函数调用时可省略传值,Java中没有相对应的概念,Kotlin的默认值参数可以实现同样功能。
- 可选参数分为
命名可选参数
与位置可选参数
- 定义参数列表时,必选参数需要放到可选参数前面
命名可选参数
使用{}
包裹;位置可选参数
需使用[]
包裹。
命名可选参数(Optional named parameter)
命名可选参数
传值时需要携带参数名称,如果不需要传值则不需要携带参数名称。
不传值的参数会使用函数定义时的默认值,如果函数定义中没有默认参数值
,则会传null
void enableFlags({bool bold, bool hidden}) {...}
// bold中传入了null、hidden中传入了true
enableFlags(hidden: true);
如果命名可选参数
添加了@required
注解,则此参数必须在在函数调用时指定,不可缺省。
@required
的使用需要引入package:meta/meta.dart
// child中不传值调用会报错
const Scrollbar({Key key, @required Widget child})
位置可选参数(Optional positional parameter)
位置可选参数
中可选取任意位置,省略其后的所有传值,
若函数定义没有默认参数值
,则会被传入null
String say(String from, String msg,
[String device, String mood]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
if (mood != null) {
result = '$result (in a $mood mood)';
}
return result;
}
// 第三个参数起可省略
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
// 函数调用无需携带参数名
// 也可以之省略第四个参数
assert(say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal');
默认参数值
函数定义时,可以指定默认参数值
。这与Kotlin的默认值参数
区别如下:
- Kotlin
默认值参数
:有默认值的参数在函数调用时自动变为可选参数
,允许缺省传参。若位置参数
的方式传参(省略指定参数名称),则指定默认值的参数起,后面的所有参数都需要指定默认值:
//kotlin
fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: String= "bbb") {
}
//位置参数:后面的参数可以都省略,但必须都有默认值
fun reformat("aaa")
//命名参数:通过参数名指定参数,不要求默认值参数后必须都指定默认值
fun reformat(str = "aaa", upperCaseFirstLetter = false)
- Dart
默认参数值
:可选参数不一定有默认参数值,如果不指定默认参数值,则缺省传参时会被传入null
因为Kotlin的默认值参数
自动变为可选参数,所以不用像Dart那样使用[]
、{}
单独定义可选参数,个人认为Kotlin的做法更优雅简洁。
扩展函数
Dart 2.6起,开始支持像Kotlin那样的扩展函数。但是写法没有Kotlin简洁
extension NumExtention<T extends num> on T {
T pow(int p) => math.pow(this, p) as T;
}
print(2.pow(5)); // 32
- 如上,扩展函数也可以使用泛型
- 在
extension
前添加下划线可以private
化 - 扩展函数只能在top-level声明,Kotlin可以在Class内部声明(但用处不大)。
扩展函数是Kotlin能提供强大DSL的基础,DSL非常适合声明式UI的书写,例如Kotlin的Anko比起Flutter写法上要优雅的多。个人认为扩展函数未来将会为Dart的生态带来很大变化。