通关 Dart 之路|异常处理之预见错误,优雅应对
学习 Dart 异常处理:预见错误,优雅应对
在程序运行过程中,异常是不可避免的。网络异常、文件读取错误、日期格式问题等,都可能引发程序中断。不仅需要处理异常以确保程序不中止,还能更轻松地排查问题。
1. 异常的触发
以下测试中,task1
方法将字符串转为数字,若传非数字,将产生转换异常,中断 task2
的执行。
void main(){
task1('a');
task2();
}
int task1(String num){
return int.parse(num);
}
void task2(){
print("Task2");
}
2. 异常的捕捉
使用 try...catch...
捕捉异常。catch
中的参数:
e
表示异常对象,如FormatException
s
是_StackTrace
,记录异常的栈信息
void main(){
try{
task1('a');
} catch(e, s){
print("${e.runtimeType}: ${e.toString()}");
print("${s.runtimeType}: ${s.toString()}");
}
task2(); // Task2
}
异常被捕获,程序不中断,task2
仍执行。
3. 自定义异常与抛出
Exception
是异常的顶层抽象类,可构造运行时类型为 _Exception
的异常对象,传入信息。
void main() {
try {
getMean("about");
} catch (e, s) {
print("${e.runtimeType}: ${e.toString()}");
print("${s.runtimeType}: ${s.toString()}");
}
}
String getMean(String arg) {
Map<String, String> dict = {"card": "卡片", "but": "但是"};
String? result = dict[arg];
if (result == null) {
throw Exception("empty $arg mean in dict");
}
return result;
}
4. 分类异常处理
可拓展 Exception
类以自定义异常类型。使用 on/catch
捕获不同异常类型。
void main() {
try {
getMean("about");
} on NoElementInDictException catch (e, s) {
// 特定异常处理
} catch (e, s) {
// 其他异常处理
}
}
5. finally 关键字
finally
用于 catch
之后,无论异常与否,都执行。避免多次重复写 finally
代码块。
void foo2(){
try {
getMean("about");
} catch (e, s) {
print("${e.runtimeType}: ${e.toString()}");
print("${s.runtimeType}: ${s.toString()}");
} finally{
print("finally block called");
}
异常处理是 Dart 编程的关键,确保程序鲁棒性和可维护性。遵循最佳实践,优雅应对异常,将让你的代码更具健壮性。
学习 Dart | 类与成员可见性
本文将深入探讨 Dart 中的类及其成员可见性,构建坚实的面向对象基础。
类的定义与实例化
Dart 使用 class
关键字定义类,通过 {}
定义类的作用域,包含成员变量和成员方法。
class $className$ {
// 类体
}
1. 类的简单定义与实例化
以 Vec2
类为例,定义包含两个 double
变量的类,用构造方法初始化。
class Vec2 {
double x;
double y;
Vec2(this.x, this.y);
}
通过构造方法实例化 Vec2
类,访问和修改成员变量:
void main() {
Vec2 p0 = Vec2(4, 3);
print("Vec2(${p0.x},${p0.y})"); // Vec2(4.0,3.0)
p0.x = 15;
print("Vec2(${p0.x},${p0.y})"); // Vec2(15.0,3.0)
}
2. 成员方法
除成员变量外,类还可以定义成员方法。例如,为 Vec2
提供 getInfo
方法获取打印信息:
class Vec2 {
double x;
double y;
Vec2(this.x, this.y);
String getInfo() => "Vec2($x,$y)";
}
调用成员方法简化代码:
void main() {
Vec2 p0 = Vec2(4, 3);
print(p0.getInfo()); // Vec2(4.0,3.0)
p0.x = 15;
print(p0.getInfo()); // Vec2(15.0,3.0)
}
3. get 与 set 关键字
get
和 set
修饰成员方法,提供属性式访问。如 length
计算向量长度:
class Vec2 {
// ...
double get length => math.sqrt(x * x + y * y);
}
使用属性式访问 length
:
Vec2 p0 = Vec2(4, 3);
print(p0.length); // 5.0
4. 类的构造方法
构造方法是连接类与对象的桥梁,特点包括无返回值、可无方法体、可对成员进行赋值。
class Vec2 {
double x;
double y;
Vec2(this.x, this.y);
}
使用构造方法实例化对象,支持命名参数:
Vec2 p0 = Vec2(4, 3);
Vec2 p1 = Vec2(argX: 4, argY: 3);
5. 命名构造
通过命名构造创建多种实例化方式,如 Vec2.polar
构造方法:
class Vec2 {
Vec2.polar(double length, double rad)
: x = length * math.cos(rad),
y = length * math.sin(rad);
}
使用命名构造创建对象:
Vec2 p1 = Vec2.polar(10, math.pi / 4);
成员和类的可见性
使用 _
前缀限制成员可见性,私有成员仅限同一文件访问。
class Vec2 {
double x;
double y;
String? _name;
Vec2(this.x, this.y);
String getInfo() => "${name}Vec2($x,$y)";
double get length => math.sqrt(x * x + y * y);
String get name => _name ?? "";
set name(String? value) {
_name = value == null ? "" : value + ": ";
}
}
限制私有成员可见性,保障封装与安全性。
静态成员与静态方法
静态成员由类直接访问,使用 static
关键字定义静态成员和静态方法:
class Person {
String name;
static String nation = "";
Person(this.name);
static void printNation() {
print("Current nation is: $nation");
}
void say() {
print("I am $name, from $nation");
}
}
使用静态成员和静态方法,无需实例化对象:
Person.nation = "Tang Dynasty";
print(Person.nation); // Tang Dynasty
Person.printNation(); // Current nation is: Tang Dynasty
通过类直接访问静态成员,实现全局共享数据和方法。
结语
本文深入介绍了 Dart 类的定义与实例化、构造方法、成员方法、可见性和静态成员等基础概念。掌握这些核心概念将帮助你更好地构建健壮的面向对象程序,为进一步探索类与类间的关系打下坚实基础。