1 方法
1.1 一等方法对象 Function
void fun() {
print('hhaha');
}
void main() {
Function f = fun; // 方法都是对象,可以赋值给Function对象
f(); // 调用fun()方法
}
Function还可以作为参数传入
void fun2(Function function) { // 没有办法标识要传递的这个方法参数和返回值
print('hhaha222');
function(); // 调用传入的方法,无参。如果传入的方法是有参的,运行时报错
}
void main() {
Function f2 = fun2; // 方法都是对象,可以赋值给Function对象
// f2(); // 运行报错,需要传参
f2(f); // 调用fun2()方法,传入方法
// 也可以传入一个匿名方法
f2(() {
print('传入的方法参数是匿名方法'); // 不会执行,需要在fun2中调用才会执行。
});
// 匿名方法可以随意定义参数和返回值
// 在fun2需要调用时,传入的参数需要和这里定义的参数类型、数量相同,否则会运行报错。
// 这就有些不方便了,那如果传入的参数错误,有什么办法可以在编译器就能检查出来呢?这就要引入typedef关键字了。
f2((int a, int b) {
return "1";
});
typedef关键字的使用
// 定义一个类型,F类型,这个F类型其实就是一个方法,接收两个int参数,返回void
typedef void F(int i, int j);
定义一个方法,将F作为参数传入。
void fun3(F f) {
f(1, 2); // 这边在编译时就会校验传参是否正确。
print('hhaha3333');
}
调用fun2()方法
// 方法1
Function f3 = fun3;
f3((int i, int j) { // 这边好像要在运行时才会报错。
});
// 方法2
fun3((i, j) { // 这边在编译时也就会校验传参是否正确。
});
如果不想使用typedef,直接将方法的原形作为参数传入也是可以的
void fun4(void f1(int i, int j)) { // 这种写法可以表达传递的这个方法参数和返回值,但写起来比较麻烦
f1(1, 2);
}
使用场景示例:
如果我们之前在java中设置一个onClick监听,需要传入接口,并实现接口的方法。但在dart中就可以直接传入一个方法接口。
typedef void onClick();
void setOnClickListener(onClick click){
click(); // 通过这种方式就可以直接回调出去了。
}
1.2 可选位置参数
可以当做是为了解决java中的方法重载问题。
如果我们提供了同一个方法名的两个方法,只是传入的参数不同。fun(int a)、fun(int a,int b)
在dart中,我们只需要提供一个方法fun(int a,int b)即可,让使用者决定传入哪个。只需要加上中括号即可
void fun(int a, int b) {}
// 可选位置参数
void fun1([int aa = 0, int bb = 0]) {
// 最新的版本中一定要给一个默认值,否则编译报错。之前版本好像没问题
}
void main() {
fun(1, 2); // 必须传两个参数
fun1(); // 可以不传参数
fun1(1); // 也可以只传一个,1会赋值个aa。如果要传bb参数,aa必须要传
fun1(1, 2); // 也可以传两个
}
1.3 可选命名参数
与可选位置参数不同的是,中括号改成大括号,就是可选命名参数
// 可选命名参数
void fun2({int aa = 0, int bb = 0}) {
// 最新的版本中一定要给一个默认值,否则编译报错。之前版本好像没问题
}
void main() {
fun2(); // 不传参数,也没问题
// fun2(1); // 只传一个参数,这样写就不行了。需要给传入的这个值命名
fun2(aaa: 1); // 带入变量名,就可以给任意一个值传值了。
fun2(bbb: 2);
fun2(bbb: 2, aaa: 1); // 顺序也可以随便传
}
1.4 默认参数值
可选位置参数和可选命名参数都使用到了默认参数值。
1.5 匿名方法
没有方法名的方法
void fun(Function function) {}
void main() {
fun(() {
});
fun((int, String) {
});
}
2 异常
void fun() {
throw Exception();
}
void main() {
// fun(); // 不需要像java中一样调用try-catch。但是也支持
try {
fun();
} catch (e) {
// 不需要声明类型,传入一个变量名。e就是抛出的异常对象
print(e);
}
try {
fun();
} catch (e, a) {
// 打印结果:Exception
print(e);
// 也可以传入两个变量名。第二个参数是StackTrace 调用栈信息。打印结果:
// #0 fun (package:untitled/%E5%BC%82%E5%B8%B8/%E5%BC%82%E5%B8%B8.dart:2:3)
// #1 main (package:untitled/%E5%BC%82%E5%B8%B8/%E5%BC%82%E5%B8%B8.dart:16:5)
// #2 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
// #3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
print(a);
}
}
在dart中可以抛出任意一种类型
void fun() {
// throw Exception(); // 在dart中不光可以抛出一个异常
// throw Error(); // 还可以抛出error
// throw 1; // 还可以抛出一个int值
// throw "异常信息"; // 抛出一个字符串
throw fun2; // 甚至是一个方法、类
}
void fun2() {
print("我是一个方法");
}
根据不同的异常类型进行不同的处理
// 在catch前添加on+抛出类型。
void main() {
try {
fun();
} on Function catch (e) {
print("抛出了一个方法 $e");
e(); // 如果抛出的是一个方法,甚至可以直接在这里调用这个方法。
} on int catch (e) {
print("抛出了一个int值 $e");
} on String catch (e) {
print("抛出了一个字符串 $e");
} on MissingPluginException catch (e) {
print("抛出了一个MissingPluginException异常 $e");
} on Exception catch (e) {
print("抛出了一个Exception异常 $e");
} finally { // finally用法和java一样
}
}
网友评论