Dart语法
Dart字符串插入变量
在dart字符串中插入变量
js
i = 1
s = f'Hello World{i}'
在python字符串中插入变量
js
String stringify(int x, int y) {
return '$x $y';
}
Dart不支持方法的重载
dart是一种动态的语言,而重载需要机遇静态类型的解析,但是dart支持可以使用命名参数的方式来实现类似于重载的效果
java中的方法重载
js
double yearlyIncome(double hourlyRate, double hoursWorkedPerYear)
double yearlyIncome(double monthlyRate, int monthsWorkedPerYear)
dart中使用命名可选参数来实现类似的功能
js
void yearlyIncome({double hourlyRate, double monthlyRate, double hoursWorkedPerYear, int monthsWorkedPerYear})
可空变量
?赋值
js
int a = null //illegal
int? a = null //legal
int? a // the iniitial value of a is null
避空运算符
js
int? a; // = null
a ??= 3;
print(a); // <-- Prints 3.
a ??= 5;
print(a); // <-- Still prints 3.
js
print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.
条件属性访问
js
myObject?.someProperty
//等效于
(myObject != null) ? myObject.someProperty : null
箭头语法
js
bool hasEmpty = aListOfStrings.any((s) {
return s.isEmpty;
});
//等效于下列代码
bool hasEmpty = aListOfStrings.any((s) => s.isEmpty);
级联运算符
使用..而不是.的好处是.返回的是表达式的结果而..返回的是表达式运算完的对象的引用,可以在此基础上继续去调用该对象所持有的方法
异常
Dart可以抛出和捕获异常,与java相比,Dart的异常都是unchecked exception。方法不用声明它们可能抛出的异常。也不需要捕获任何异常。使用try, catch, on关键字处理异常。
js
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再次抛出
js
try {
breedMoreLlamas();
} catch (e) {
print('I was just trying to breed llamas!');
rethrow;
}
抛出异常完毕之后仍然要执行的代码
js
try {
breedMoreLlamas();
} catch (e) {
// ... handle exception ...
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
列表构造
js
Point.fromJson(Map<String, double> json)
: x = json['x']!,
y = json['y']! {
print('In Point.fromJson(): ($x, $y)');
}
命名构造方法
为了允许一个类具有多个构造方法
js
class Point {
double x, y;
Point(this.x, this.y);
Point.origin()
: x = 0,
y = 0;
}
工厂构造方法
工厂构造方法能够返回其子类甚至null对象,使用factory关键字进行工厂构造
js
class Square extends Shape {}
class Circle extends Shape {}
class Shape {
Shape();
factory Shape.fromTypeName(String typeName) {
if (typeName == 'square') return Square();
if (typeName == 'circle') return Circle();
throw ArgumentError('Unrecognized $typeName');
}
}
函数特性
在dart中,函数可以直接作为变量也可以作为参数传递,函数是一个对象,类型为Function
抽象类
dart定义抽象类
dart中的抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类的借口
js
// 定义抽象类 通过abstract关键字类定义
abstract class A{
}
// 抽象类不能被实例化
void main(){
// 实例化抽象类就报错
var cat = new A();
}
定义抽象方法
js
// 定义抽象方法
abstract class Person{
// 抽象方法
// 抽象方法不能使用abstract声明
// 如果使用就会报错
void eat();
}
// 不能在非抽象类中定义抽象方法
class Man{
// 属性
String name = "小美";
// 方法
void getInfo(){
print("我是${name}");
}
// 抽象方法
void sayHello(); // 报错
}
抽象类也可以有非抽象方法
js
// 定义一个抽象类
abstract class Person{
// 抽象方法
eat();
// 非抽象方法
printInfo(){
print("我就是抽象类里的一个非抽象方法");
}
}
// 子类继承抽象类
class Man extends Person{
String name;
Man(this.name){}
// 子类必须实现抽象类的方法
@override
eat() {
print("${this.name}喜欢吃");
}
}
// 子类继承抽象类
class Child extends Person{
String name;
Child(this.name){}
// 子类必须实现抽象类的方法
@override
eat() {
print("${this.name}喜欢写代码");
}
}
void main(){
Man man = new Man("小美");
Man.eat(); // 小美喜欢吃
// 子类调用继承的抽象类中的非抽象方法
man.printInfo();
Child child = new Child("嘟嘟");
child.eat(); // 嘟嘟喜欢吃
child.printInfo(); // 我就是抽象类里的一个非抽象方法
}
抽象类的说明
- 如果子类继承抽象类必须得实现里面的抽象方法
- 如果抽象类被当作接口实现的话,子类必须得实现抽象类里面定义的所有属性和方法
- 抽象类不能被实例化,只有继承他的子类可以
- 抽象类通常用来定义接口
- 抽象类通常具有抽象方法
- 有抽象方法的类一定要声明为抽象类
接口
- 普通类和抽象类都可以作为接口,类就是接口
- 一个普通类要实现某个接口,覆写接口接口类的每个成员
- 如果是复用已有类的接口,使用继承
- 如果只是使用已有类的外在行为,使用接口
- 每个类都隐式的定义了一个包含所有实例成员的接口
js
// 抽象类A接口
abstract class A{
String name;
// 抽象方法
printA();
}
// 抽象类B接口
abstract class B{
int age;
// 抽象方法
printB();
}
// Student 类实现 A和B 两个接口
class Student implements A,B{
// 覆写接口的属性
@override
String name;
int age;
Student(this.name,this.age);
// 实现A接口的方法
@override
void printA(){
print("实现A接口的方法");
}
// 实现B接口的方法
@override
void printB(){
print("实现B接口的方法");
}
// 子类自己的方法
void sayHello(){
print("大家好, 我叫${name},今年${age}岁了");
}
}
// 入口函数
void main(){
// 实例化子类
Student xm = new Student("小刚",8);
xm.printA(); // 实现A接口的方法
xm.printB(); // 实现B接口的方法
xm.sayHello(); //大家好, 我叫小刚,今年8岁了
}
接口和继承的区别
- extends是继承,就算有些父类的方法不覆写,子类的实例也能使用父类的方法
- implement是实现接口,不管实现多少父类接口,父类里的所有方法都需要覆写
枚举
- 使用enum关键字定义一个枚举类型
- 枚举是一种有穷序列集的数据类型
- 常用于代替常量,控制语句等
- 枚举中的每个值都有index,返回索引,索引从0开始
- 枚举中的每个值都可以使用values属性列举出来
- 枚举不能被子类化,混合或实现
- 枚举不能被显式实例化
js
// 定义枚举
enum Color {
red,
green,
blue,
// 不能指定值,会报错的
// whie = "#fff"
}
// 入口函数
void main(){
// index 获取索引
print(Color.red.index);
print(Color.green.index);
print(Color.blue.index);
// value
print(Color.red);
// 枚举值
List list = Color.values;
print(list); //[Color.red, Color.green, Color.blue]
// 流程控制
var color = Color.red;
switch(color){
case Color.red:
print("红色");
break;
case Color.green:
print("绿色");
break;
case Color.blue:
print("蓝色");
break;
}
}
混入
- 使用Mixin定义混入类
- Minxin类只能继承Object,不能继承其他类
- Mixin类似多继承
- Mixin类不能声明构造函数,不能调用super
- 一个类可以混入多个Mixin类
- 使用with关键字进行混入
- 在混入多个类时,类中具有相同的属性或方法,后混入的会覆盖数据
- 混入不影响继承
js
// 使用mixin关键字定义混入类
mixin A{
String name = "AA";
printA(){
print("这是普通类A");
}
}
mixin B{
String name = "BB";
printB(){
print("这是普通类B");
}
}
class Student with A,B{
}
// 入口函数
void main(){
// 实例化子类
Student student = new Student();
print(student.name); // BB
//在混入多个类时,类中具有相同的属性或方法,后混入的会覆盖数据
student.printA(); // 这是普通类A
student.printB(); // 这是普通类B
}
异步支持
Dart的事件循环
Dart是事件驱动的体系结构,该结构基于具有单个事件循环和两个队列的单线程执行模型。Dart的两个队列分别是MicroTask queue
微任务队列和Event queue
事件队列
我们可以看出,将任务加入到MicroTask
中可以被尽快执行,但也需要注意,当事件循环在处理MicroTask
队列时,Event
队列会被卡住,应用程序无法处理鼠标单击、I/O消息等等事件。
调度任务
将任务添加到MicroTask
队列中
js
import 'dart:async';
void myTask(){
print("this is my task");
}
void main() {
# 1. 使用 scheduleMicrotask 方法添加
scheduleMicrotask(myTask);
# 2. 使用Future对象添加
new Future.microtask(myTask);
}
将任务添加到Event
队列中
js
import 'dart:async';
void myTask(){
print("this is my task");
}
void main() {
new Future(myTask);
}
延时任务
js
new Future.delayed(new Duration(seconds:1),(){
print('task delayed');
});
创建Future
Future()
Future().microtask
Future().sync()
立刻执行Future().value()
Future.delayed()
Future().error
注册回调
js
import 'dart:async';
void main() {
print("main start");
Future fut =new Future.value(18);
// 使用then注册回调
fut.then((res){
print(res);
});
// 链式调用,可以跟多个then,注册多个回调
new Future((){
print("async task");
}).then((res){
print("async task complete");
}).then((res){
print("async task after");
});
print("main stop");
}
async和await
将async
关键字作为方法声明的后缀时,具有如下意义
- 被修饰的方法会将一个
Future
对象作为返回值 - 该方法会同步执行其中的方法的代码直到第一个await关键字,然后它暂停该方法其他部分的执行
- 一旦由await关键字引用的Future任务执行完成,await的下一行代码将立即执行
js
// 导入io库,调用sleep函数
import 'dart:io';
// 模拟耗时操作,调用sleep函数睡眠2秒
doTask() async{
await sleep(const Duration(seconds:2));
return "Ok";
}
// 定义一个函数用于包装
test() async {
var r = await doTask();
print(r);
}
void main(){
print("main start");
test();
print("main end");
}