变量
创建并初始化变量
// 不指定变量类型,自动推断为String;可通过指定类型改变
var name = 'Bob';
// 一个对象不受限于单一类型时,使用 Object 或 dynamic(谨慎使用)
Object name = 'Bob';
dynamic name = 'Bob';
// 直接指定类型
String name = 'Bob';
空安全
空安全能够防止意外访问 null 的变量而导致的错误,如调用值为null的属性或方法会报错(toString() 方法和 hashCode 属性例外)
如果出现错误,会在编译时报错,不会在运行时报错
空安全的3个关键点
- 使用?控制变量是否可空
String? name // Nullable type. Can be `null` or string.
String name // Non-nullable type. Cannot be `null` but can be string.
- 可空变量默认初始化为null,非可空变量需要自己初始化值(不必在声明变量时初始化变量,但在使用之前需要为其赋值)
- 不能在可空类型的表达式上访问属性或调用方法(toString() 方法和 hashCode 属性例外)
延迟初始化变量
顶级变量(指在整个 Dart 程序或库的最外层作用域中定义的变量)和类变量((也称为静态变量)是与类本身相关联而不是与类的实例相关联的变量)是延迟初始化的,它们会在第一次被使用时再初始化。
当一个 late 修饰的变量在声明时就指定了初始化方法,那么内容会在第一次使用变量时运行初始化
// This is the program's only call to readThermometer(). 如果 temperature 变量从未被使用,则 readThermometer() 这个开销较大的函数也永远不会被调用
late String temperature = readThermometer(); // Lazily initialized.
终值 (final) 和常量 (const)
一个 final 变量只能设置一次,const 变量是编译时常量。(const 常量隐式包含了 final。)
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
// 使用 const 修饰 编译时常量 的变量
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
// 创建常量 值(values),以及声明 创建(create) 常量值的构造函数。任何变量都可以拥有常量值。
var foo = const [];
final bar = const [];
const baz = []; // Equivalent to `const []`
操作符 Operators
级联符号...和?..
// 以下两段代码相等
// 代码1
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
// 代码2
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
如果级联操作对象可为空,使用?..
// 以下两段代码相等
// 代码1
querySelector('#confirm') // Get an object.
?..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'))
..scrollIntoView();
// 代码2
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();
嵌套级联
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = '[email protected]'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
展开运算符.../...?
实际并不是运算符,视为在运算符中优先级最低
[...a + b]
注释Comments
// Single-line comments
/*
Multi-line comments
*/
/// Documentation comments
/** Documentation comments
注解Metadata
- 以@开头,后面是对编译时常量的引用(例如deprecated)或对常量构造函数的调用。
- 所有Dart代码都可以使用四种注释:@Deprecated, @deprecated, @override, @pragma.
class Television {
/// Use [turnOn] to turn the power on instead.
@Deprecated('Use turnOn instead')
void activate() {
turnOn();
}
/// Turns the TV's power on.
void turnOn() {...}
// ···
}
- 可以自定义注解
class Todo {
final String who;
final String what;
const Todo(this.who, this.what);
}
@Todo('Dash', 'Implement this function')
void doSomething() {
print('Do something');
}
- Metadata can appear before a library, class, typedef, type parameter, constructor, factory, function, field, parameter, or variable declaration and before an import or export directive.
库和导入 Libraries & imports
- 导入库
import 'dart:html'; // For built-in libraries
import 'package:test/test.dart'; // libraries provided by a package manager
- 指定前缀
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Uses Element from lib1.
Element element1 = Element();
// Uses Element from lib2.
lib2.Element element2 = lib2.Element();
- 导入库的部分内容
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
- 延迟加载deferred as
// 标记延迟加载
import 'package:greetings/hello.dart' deferred as hello;
// 使用前先调用loadLibrary(),loadLibrary()可多次调用,库仅加载一次
Future<void> greet() async {
await hello.loadLibrary();
hello.printGreeting();
}