变量
变量的声明以及赋值:
//如果不初始化,则后续可以赋值任意类型,最终类型是dynamic类型,dynamic类型不会检测成员
var name = "Bozo";
在声明变量的时候,也可以选择使用具体的数据类型:
//使用确定类型定义变量,赋值必须是相同类型
String name = "bozo";
int age = 12;
double height = 176.3;
bool onLine = true;
没有初始化变量默认值都为
null,即使变量类型为bool或者int
Dart中的基本数据类型:num、double、int、String、List、Set、String、map、bool、runes、Symbol、Object、dynamic
Dart中所有数据类型都是对象,都继承自
Object类,null也继承自Object类
const&final
使用const跟final定义的变量都只能赋值一次,并且在声明的时候必须进行初始化。
使用const定义的集合都是只读的,特性会传递到子元素,在内存中会复用相同内容对象,而final则不会作用于子元素,在内存中也不会复用相同对象
//不可以通过 list[0] = 5; 来修改集合中元素的值, 如果换做final来定义则可以修改
const list = [1,2,3,4];
const list2 = [1,2,3,4];
//此时输出的结果为 true, 如果集合是用final定义的则输出结果为 false
print(identical(list, list2));
实例变量可以为
final但是不能是const
方法
方法可以赋值给变量,也可以当作其他方法的参数,以下为定义方法的示例:
bool isEmpty(String str){
return str == null || str == "";
}
//可以忽略类型定义
isEmpty(str){
return str == null || str == "";
}
//如果是只有一个表达式的方法,则可以使用缩写语法来定义
isEmpty(str) => str == null || str == "";
在Dart中方法还可以设置可选参数,以及设置默认值
void main() {
printInfo("Bozo", 13, true);
//可选位置参数
// printInfo("Bozo", false);
//可选命名参数
// printInfo(name: "Bozo", showAge: false);
//指定默认值
// printInfo(name: "Bozo", showAge: true);
}
printInfo(name, age, showAge) {
if (showAge) {
print("name:$name,age:$age");
} else {
print("name:$name");
}
}
//可选位置参数
printInfo(name, showAge, [age]) {
......
}
//可选命名参数
printInfo({name, age, showAge}) {
......
}
//指定默认值
printInfo({name, age = 12, showAge}) {
......
}
所有函数都有一个返回值,如果没有指定返回值,则默认把
return null;作为函数得最后一个语句执行
操作符

操作符重载
以下操作符可以被重载

例如重写+跟-操作符
class Vector{
final int x;
final int y;
Vector(this.x, this.y);
Vector operator +(Vector v){
return Vector(x + v.x, y + v.y);
}
Vector operator -(Vector v){
return Vector(x - v.x, y - v.y);
}
}
void main(){
Vector v1 = Vector(4, 3);
Vector v2 = Vector(2, 1);
Vector v3 = v1 - v2;
Vector v4 = v1 + v3;
//print: v3:x=2,y:2
print("v3:x=${v3.x.toString()},y:${v3.y.toString()}");
//print: v4:x=6,y:5
print("v4:x=${v4.x.toString()},y:${v4.y.toString()}");
}
如果覆写的操作符是
==,则还应覆写对象的hashCodegetter 函数
类型判定操作符
as、is、is!操作符是在运行时判定对象类型的操作符
| 操作符 | 解释 |
|---|---|
| as | 类型转换 |
| is | 如果对象是指定的类型返回true |
| is! | 如果对象是指定的类型返回false |
级联操作符
级联操作符 (..) 可以在同一个对象上 连续调用多个函数以及访问成员变量,使用级联操作符可以避免创建 临时变量
void main() {
Person()
..name = 'bozo'
..age = 12
..contact = (new Contact()
..phoneNumber = '126854315'
..email = 'bozo@gmail.com')
..showInfo();
}
class Person {
String name;
int age;
Contact contact;
showInfo() {
print("Name:${this.name},Age:${this.age},PhoneNumber:${this.contact.phoneNumber},Email:${this.contact.email}");
}
}
class Contact {
String phoneNumber;
String email;
}
异常
抛出异常
throw new FormatException('Expected at least 1 section!');
//还可以抛出任意对象
throw 'Out of llamas!'
捕获异常
try {
throwExceptionsFuc();
} on FormatException {
...
} on Exception catch (e) {
...
} catch (e) {
...
} finally {
...
}
}
可以使用
on或者catch来声明捕获语句,也可以同时使用。使用on来指定异常类型,使用catch来捕获异常对象,函数catch可以有一个或两个参数,第一个参数为抛出的异常对象,第二个为堆栈信息
还可以使用rethrow关键字来把捕获的异常重新抛出
try{
testFuc();
} catch (e) {
...
//重新抛出异常
rethrow;
}
类
Dart中每个对象都是一个类的实例,所有类都继承于Object。
构造函数
在Dart中可以使用this关键字来简化构造函数的实现:
class Person{
String name;
int age;
//原始写法
Person(String name, int age){
this.name = name;
this.age = age;
}
//使用this关键字简化写法
Person(this.name, this.age);
}
如果没有定义构造函数,跟Java中一样会有一个默认的无参构造
使用命名构造函数可以为一个类实现多个构造函数,如果要在一个构造函数中调用其他构造函数则使用重定向构造函数。
void main() {
Person person1 = new Person("Bozo", 17);
Map map = new Map();
map['name'] = "bozo";
map['age'] = 18;
Person person2 = new Person.fromMap(map);
}
class Person {
String name;
int age;
Person(this.name, this.age);
//命名构造函数
Person.fromMap(Map map) {
this.name = map['name'];
this.age = map['age'];
}
//重定向构造函数
Person.byName(name) : this(name, 0);
}
如果要类提供一个状态不变的对象,则可以把对象定义为编译时常量。需要定义一个const构造函数,并且声明所有的变量为final。使用常量构造函创建的对象具有复用性,前提是对象的成员变量值相同。
class Car {
final String color;
const Car(this.color);
static final Car car = const Car("red");
}
void main(){
Car car1 = const Car("red");
Car car2 = const Car("black");
//断言执行通过,car1跟car为同一个对象
assert(identical(car1, Car.car));
//断言执行失败
assert(identical(car2, Car.car));
}
如果一个构造函数不是总是返回一个新的对象,则可以使用factory关键字来创建工厂方法构造函数
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to the _ in front
// of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = new Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) {
print(msg);
}
}
}
void main(){
var logger = new Logger('UI');
logger.log('Button clicked');
}
工厂方法无法访问
this
extends 跟 implements
-
extends:继承其他类的属性以及方法,在dart中可以使用with关键字来实现多继承class A extends B with C,D{ ... } -
implements:一个类可以通过implements关键字来实现一个或者多个接口, 并实现每个接口定义的 API
枚举
使用 enum 关键字来定义枚举类型,枚举中每个值都有一个index的属性(从0开始)。枚举的values常量可以返回所有的枚举值
enum Color{
RED,
GREEN,
BLUE
}
void main(){
List<Color> colors = Color.values;
assert(colors[2] == Color.BLUE);
}
泛型
在Dart中使用泛型的方式与Java类似:
abstract class Cache<T>{
T getByKey(String key);
void cacheByKey(String key, T value);
}
限制泛型的具体类型:
class SomeClass<T extends SomeBaseClases>{
...
}
泛型函数:
T findByIndex<T>(List<T> data, int index) {
return data == null ? data[index] : null;
}
库
使用 import 来导入库
//内置库使用 dart:scheme
import 'dart:io';
//其他库使用文件系统路径或者 package:scheme
import 'package:libs/utils.dart';
如果导入的两个库具有冲突的标识符,则可以使用库的前缀来区分,例如lib1跟lib2中都存在名为SomeClass的类:
import 'package:libs/lib1.dart';
import 'package:libs/lib2.dart' as lib2;
...
SomeClass class1 = new SomeClass();
lib2.SomeClass class2 = new lib2.SomeClass();
如果只想导入库的一部分内容可以使用 show 跟 hide
// 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:deferred/hello.dart' deferred as hello;
//当需要使用的时候,使用库标识符调用loadLibrary()函数来加载库
hello.loadLibrary();
hello.sayHello();
- 一个库可以调用
loadLibrary()函数,但该库只会载入一次- 延迟加载库的常量在导入的时候是不可用的。 只有当库加载完毕的时候,库中常量才可以使用。
- 在导入文件的时候无法使用延迟库中的类型。 如果你需要使用类型,则考虑把接口类型移动到另外一个库中, 让两个库都分别导入这个接口库。
- Dart 隐含的把
loadLibrary()函数导入到使用deferred as *的命名空间*中。loadLibrary()方法返回一个 Future。
异步
异步方法的声明是添加 async 关键字,如:
...
checkVersion() async{
...
}
使用await来等待异步方法返回:
...
//要使用 await,其方法必须带有 async 关键字
checkVersion() async{
var version = await getVersionInfo();
...
}