Exceptions
- Dart 中的异常信息捕获处理:
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
- Dart中的异常信息捕获后可以再次抛出,使用rethrow关键字
- 可以指明捕获一个或者两个参数,第一个参数是exception,第二个参数是堆栈信息StackTrace
try {
// ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
void misbehave() {
try {
dynamic foo = true;
print(foo++); // Runtime error
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // Allow callers to see the exception.
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
- 使用finally语句块,即使有异常信息抛出,如果没有相应的catch语句,也会先执行finally语句块中的代码;如果有相匹配的catch语句,则会先执行catch语句块,再执行finally语句块
try {
breedMoreLlamas();
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
try {
breedMoreLlamas();
} catch (e) {
print('Error: $e'); // Handle the exception first.
} finally {
cleanLlamaStalls(); // Then clean up.
}
Classes
构造函数
Dart中对于构造函数有个特殊的语法糖:
class Point {
num x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
默认构造函数 Default constructors
-
如果不声明一个构造函数,会默认生成一个,默认构造函数是没有参数的,并且调用父类的无参构造函数。反之,如果已经声明了一个构造函数,那么就不会生成默认构造函数。
命名构造函数 Named constructors
- 使用命名构造函数,可以为一个类实现多个构造函数,或者提供额外的说明:
class Point {
num x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
- 如果想要通过父类的命名构造函数来创建一个子类的对象,那么必须在子类中实现父类中的该构造函数
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
//Person类中没有默认的构造函数,这时候子类必须要手动调用父类的一个构造函数,如下在函数体前使用:super. XXX
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
父类的构造函数参数没有引用当前类对象this的权限,所以,其参数只能使用static静态方法,不能使用实例方法。
初始化器列表 Initializer lists
- Initializer lists总是最先执行的,比父类的构造函数还要先执行
- 为类中的final字段设置值时,使用Initializer lists很方便:
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
//使用逗号分隔初始化器列表字段
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
- 在一个类中,一个构造函数可以使用this关键字代理给另一个构造函数,如:
class Point {
num x, y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}
- 使用常量构造函数可以创建一个不变的对象,可以用作单例模式:
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}