变量
- var声明变量;
- late 声明将来不为空的延时变量;
- final const 声明不可变变量;
- const 编译时常量,可以用其他const变量为其赋值;
内置类型
- Numbers: init, double
- Strings String
- Booleans bool
- Lists (arrays)
- Sets (Set)
- Maps (Map)
- Runes (常用语在Characters API中进行字符替换)
- Symbols (Symbol)
- null (Null)
字符转数字
var one = int.parse('1')
var one = double.parse('1.1')
数字转字符
String one = 1.toString()
String two = 1.131415.toStringAsFixed(2);
var s = 'string as'
'${s}' 可以省略为 '$s'
拼接字符串方式 多行 或者 +
var a = '123' + '456'
var a = '123'
'456';
三个单引号,三个双引号可以创建多行
var s1 = '''
asdads
asdasdas
''';
在字符串前加r可以输出不转义的字符串
var s = r'asd \n adasd '
Lists 集合
集合中if,集合中for
var nav = [ 'home', 'fruint', if(true) 'out']
var listArr = [1,2,3]
var listfor = [ '#0', for(var i in listArr) '$i']
Sets
特定元素的无序集合
var sets = {'aaa','bbb','ccc'};
sets.add('ddd')
sets.length
Maps
var gifts = {
'first': 'partridge',
'second': 'asdadsa ',
'third': 'asdasd e1 '
}
Runes
- 表示Unicode字符:\uXXXX, XXXX为四位数的16进制数字:心形字符(♥)的 Unicode 为 \u2665
- 不是四位数的16进制数字,需要使用大括号括起来,大笑的 emoji 表情(😆)的 Unicode 为 \u{1f600}
函数
bool isEqual(int a, int b){
return a == b
}
bool isEqual(int a, int b) => a == b
参数
- 必要参数 在数定义在参数列表前面
- 可选参数 定义在必要参数后面
- 可选参数 可以是 命名参数 或者 位置的
命名参数
默认是可选参数,除非被标记为required
定义函数
void func({bool? bold, bool? hidden})
调用
func(bold: true, hidden: false)
命名参数也使用required
标识
void func({bool? bold, required bool? hidden})
可选位置参数
void func(bool a, bool b, [String? c]){
if(c != null) return c;
}
默认参数值
可以为命名参数和位置参数设置默认值,没有默认值的时候默认为null
void func({bool a = true}){...}
位置参数设置默认值
void say(String from, String msg, [String device = 'device name']){
return '$from says $msg with a $device'
}
main()函数
程序入口
匿名函数,变量作用域,闭包等和js类似
返回值默认为null
运算符
大致与js相似
类型判断运算符
- as 类型转换
(employee as Person).firstName = 'Bob';
// employee 为 null 会抛出异常
- is 类型判断
if(employee is Person){
employee.firstName = 'Bob'
}
// employee 为 null 不会抛出异常
- is! 与is 相反 相当于 is not
赋值运算符
b ??= value
// 如果b是null,则赋值value,如果b不为null,则保持不变
条件表达式
- 三元表达式 与js一样
- ??用法
a ?? b
// a 不为 null 结果为 a
// a 为 null 结果为 b
级联运算符
连续调用 ..
// 例子
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
// 级联用法
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
?..
如果为空则不执行后续
querySelector('#confirm') // Get an object.
?..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
流程控制
与js一致
- if(){}else{}
- for(){}
- for(var a in arr){}
- arr.forEach()
- while(true){}
- do{}while()
- break continue
- switch case break continue (每个case都有局部变量)
断言
条件为false时,可以打断代码执行
assert(txt != null)
异常
抛出异常
throw 可以抛出任意异常对象
优秀的代码通常会抛出 Error
或 Exception
类型的异常。
捕获异常
- on可以指定异常类型
- catch可以捕获异常对象
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');
}
- rethrow 可以降异常再次抛出
finally
始终执行
try{
...
}finally{
...
}
构造函数
var p1 = Point(2,2);
常量构造函数,创建编译时常量
var p = const ImmutablePoint(2,2)
Object.runtimeType
用来获取对象类型
实现构造函数
class Point{
double x = 0;
double y = 0;
// 用参数赋值
Point(double x, double y){
this.x = x;
this.y = y;
}
// 语法糖
Point(this.x, this.y);
}
子类调用父类时候
1 子类初始化列表
2 调用父类的匿名无参数构造函数
3 子类的constructor
如果父类没有匿名无参数构造函数,则子类必须调用父类的一个构造函数用:
指定
class Children extends Person{
Children() : super.fromJson(...);
}
抽象
abstract
抽象方法,抽象类 定义不实现
隐式接口
只想调用方法但是不想继承的时候
implements
// A person. The implicit interface contains greet().
class Person {
// In the interface, but visible only in this library.
final String _name;
// Not in the interface, since this is a constructor.
Person(this._name);
// In the interface.
String greet(String who) => 'Hello, $who. I am $_name.';
}
// An implementation of the Person interface.
class Impostor implements Person {
String get _name => '';
String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
实现多个类接口
class Point implements Comparable, Location {...}
重写类成员
class SmartTelevision extends Television {
@override
void turnOn() {...}
// ···
}
noSuchMethod 如果调用了不存在的方法或者变量会触发,可以重写来做出响应
class A {
// Unless you override noSuchMethod, using a
// non-existent member results in a NoSuchMethodError.
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: '
'${invocation.memberName}');
}
}
枚举
enum Color {red, green, blue}
assert(Color.red.index == 0)
获取全部枚举值
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
静态类和静态方法 static
静态方法不能使用this,但是可以访问静态变量
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
static double distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
库
import 'dart:html'
import 'package: src/test.dart'
import 'package: src/test.dart' as lib2;
导入一部分
import 'package:lib1/lib1.dart' show foo;
import 'package:lib1/lib1.dart' hide foo;
懒加载
import 'package:greetings/htllo.dart' deferred as hello;
Future<void> greet() async{
await hello.loadLibrary();
hello.printGreeting();
}
创建包
主 Library 文件 shelf.dart
在 lib 目录下,通过 shelf.dart
文件导出 lib/src 目录下的若干文件。为了不导出过多的 API,并且为开发者提供公开的 API 的概览, shelf.dart
使用了 show
来指定哪些内容需要导出:
export 'src/cascade.dart' show Cascade;
export 'src/handler.dart' show Handler;
export 'src/hijack_exception.dart' show HijackException;
export 'src/middleware.dart' show Middleware, createMiddleware;
export 'src/middleware/add_chunked_encoding.dart' show addChunkedEncoding;
export 'src/middleware/logger.dart' show logRequests;
export 'src/middleware_extensions.dart' show MiddlewareExtensions;
export 'src/pipeline.dart' show Pipeline;
export 'src/request.dart' show Request;
export 'src/response.dart' show Response;
export 'src/server.dart' show Server;
export 'src/server_handler.dart' show ServerHandler;
条件导入
export 'src/hw_none.dart' // Stub implementation
if (dart.library.io) 'src/hw_io.dart' // dart:io implementation
if (dart.library.html) 'src/hw_html.dart'; // dart:html implementation
该代码的作用如下:
- 在一个可以使用
dart:io
的 app 中(例如一个命令行应用),导出src/hw_io.dart
。 - 在一个 web 应用中可以使用
dart:html
导出src/hw_html.dart
。 - 若是其他情况,则导出
src/hw_none.dart
。
要条件导入一个文件可以使用和上面一样的方式,仅需将 export
改为 import
即可。
所有条件导出的库必须实现相同的 API。下面是 dart:io
实现的一个例子
异步
与js类似
Future<void> checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
main函数也可以使用
Future<void> main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}
生成器
同步生成器,返回Iterable对象
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
异步生成器,返回Stream对象
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
递归调用,可以使用yield*
提升性能
terable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
类型别名
typedef IntList = List<int>;
IntList il = [1, 2, 3];
typedef ListMapper<X> = Map<X, List<X>>;
Map<String, List<String>> m1 = {}; // Verbose.
ListMapper<String> m2 = {}; // Same thing but shorter and clearer.
文档注释
/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
///
/// Just like any other animal, llamas need to eat,
/// so don't forget to [feed] them some [Food].
class Llama {
String? name;
/// Feeds your llama [food].
///
/// The typical llama eats one bale of hay per week.
void feed(Food food) {
// ...
}
/// Exercises your llama with an [activity] for
/// [timeLimit] minutes.
void exercise(Activity activity, int timeLimit) {
// ...
}
}