Dart常用功能语法——只记录和OC、Swift不同的地方
- 打印变量
打印变量:$变量名
打印表达式: ${表达式}
void main() {
//输出变量
String name = '张三';
num age = 12;
num height = 1.77;
print('我叫$name, 出生于${DateTime.now().year - age}, 身高$height');//打印 我叫张三, 出生于2009, 身高1.77
}
-
一些重要概念(要记在脑子里)
1.可以放在变量中的所有东西,都是对象,都是类的实例。都继承Object类。
2.强类型语言。支持类型推断,故可省略变量的类型。
3.空安全。默认变量不可为null,否则需要在类型后面加上问号?,表示该变量可以为null。
4.When you want to explicitly say that any type is allowed, use the typeObject?
(if you’ve enabled null safety),Object
, or — if you must defer type checking until runtime — the special typedynamic
.(还没理解透)
5.支持泛型类型
6.支持顶级函数。即可在类以为定义函数,或函数内定义函数。
7.Similarly, Dart supports top-level variables, as well as variables tied to a class or object (static and instance variables). Instance variables are sometimes known as fields or properties.(这好像没啥好说的)
8.和Java不同,dart没有public, protected, 和 private这类修饰词,如果标识符以下划线开头,那么该标识符对应的标量就是私有的。
9.Identifiers can start with a letter or underscore (_), followed by any combination of those characters plus digits.(没啥好说的) -
变量
void main() {
//1.变量默认值
//可空变量的默认值是null
num? age;
if (age == null) {
print('年龄为空'); //打印 年龄为空
}
//不可为空的变量默认值需要手动去初始化
num height = 1.77;
print('身高$height'); //打印 身高1.77
//2.late变量(多用于类成员属性的初始化),使用这个关键字意味着
//2.1声明一个非空的变量
//2.2延迟初始化变量
late String name;
name = '赵六';
print(name); //打印 赵六
//3.final和const,被这两个关键字修饰的变量不可以修改。const是隐式的final
//注意:实例变量可以用final修饰,不可以用const
final Persion p;
// const Persion p2;//会报错
//使用区别:
//3.1 final:多用于定义不可修改的常量
//3.2 const:多用于隐式定义不可修改的常量,例如:给flutter组件的child属性赋值时,可以使用const
}
- 基本数据类型
//int类型
int age = 28;
print(age);
//double类型
double height = 1.88;
print(height);
//字符串
String name = 'bob';
print(name);
//常量
final double pi = 3.14;
print(pi);
// pi = 3.141596;//修改会报错,因为final定义的变量是不可修改的
const double pi2 = 3.14;
print(pi2);
// pi2 = 3.141596;//修改会报错,因为const定义的变量是不可修改的
//num类型,int和double都是num类型
num numberValue = 3;
print(numberValue);
numberValue = 3.1;
print(numberValue);
//布尔类型
bool enable = 1==1;
print(enable);
//list类型,也即是array。
List chars = ['a','b','c'];
print(chars);
print(chars.length);
print(chars[0]);
//set类型
Set student_no = {'1001','1002','1003'};
print(student_no);
student_no.add('1004');
print(student_no.length);
//map类型
Map letters = {'A':'a', 'B':'b'};
print(letters);
letters['C'] = 'c';
print(letters.length);
print(letters['C']);
- 类型转换
final double pi = 3.14;
var pi_str = pi.toString();
print('str = '+pi_str);
var pi_double = double.parse('3.1415926');
print(pi_double);
- 函数
//Function类型。dart中,函数也是对象
sayHello(){
print('hello dart');
}
sayHello();
//函数的箭头语法(当方法体中只有一个 表达式 时,可以使用箭头语法)
String greet(String name) => 'hello '+name;
print (greet('Bob'));
//命名可选参数{}
void printUser(String name, {int age = 0}){
print('name='+name+', age='+age.toString());
}
printUser('Jhon', age:10);
//可选参数[]
void printUser2(String name, [double height = 0.0]){
print('name='+name+', height='+height.toString());
}
printUser2('Tony');
printUser2('Tony', 1.70);
//匿名函数(有时候也被称为 lambda 或者 closure )
//定义:([[TYPE] param1[,...]]) {codeBlock}
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item){
print('${list.indexOf(item)}: $item');
});
//或者使用箭头语法
list.forEach((item) => print('${list.indexOf(item)}: $item'));
}
- 运算符
void main() {
//算数运算符 ~/
print(5 ~/ 2); //打印2
//类型判定运算符 as is is!
//as:强制类型转换
dynamic persion = Persion();
// children.name = '张三';//会报错
(persion as Persion).name = '张三';
print(persion.name); //打印张三
dynamic persion2 = Persion();
Persion p = persion2 as Persion;
p.name = '小明';
print(p.name); //打印 小明
//is:类型判断,是xxx的意思
if (persion is Persion) {
print('是个人'); //打印 是个人
}
//is!:is的取反,不是xxx的意思
if (persion is! Robot) {
print('人可不是机器人'); // 打印 人可不是机器人
}
//赋值运算符 ??= :只有当左边的变量为null时,才会将右边的值赋值给变量
var value1;
value1 ??= 2;
print(value1); // 打印 2
var value2 = 1;
value2 ??= 2;
print(value2); //打印 1
//级联运算符 .. :实现对同一个对像进行一系列的操作
var persion3 = Persion()
..name = '李四'
..age = 12
..height = 1.77;
print(persion3.name! +
' ' +
persion3.age.toString() +
' ' +
persion3.height.toString()); //打印 李四 12 1.77
}
class Persion {
String? name;
double? height;
int? age;
}
class Robot {}
- 控制流程语句
void main() {
//iterable接口对控制流程的增强
//dart中的集合默认都实现了iterable接口
var candidate = [
Persion(name: '张三', age: 12),
Persion(name: '李四', age: 18),
Persion(name: '王五', age: 20)
];
candidate.forEach((element) {
print(element.name! +
'---' +
element.age.toString()); // 打印出 张三---12 李四---18 王五---20
});
//实现iterable接口,还可以做过滤操作
candidate.where((element) => element.age! >= 18).forEach((element) {
print(
element.name! + '---' + element.age.toString()); // 打印出 李四---18 王五---20
});
//断言语句:assert 语句只在开发环境中有效, 在生产环境是无效的
assert(1 > 2, '断言成功,下面的语句将不会执行');
print('我被执行了');
}
class Persion {
String? name;
double? height;
int? age;
Persion({this.name, this.height, this.age});
}
- 类
void main() {
//类
//使用特殊点语法:?. 可以避免左边对象可能为 null , 导致的异常
var p = Person();
print(p.house?.address); //打印 null,如果将?.换成. 那么运行就会报错
//dart中的类和swift中一样,属性都需要在实例化的时候赋值,例如Point类
var point1 = Point(3, 5);
print(point1); //打印 Instance of 'Point'
var point2 = Point.fromJson({'x': 2, '7': 8});
print(point2); //打印 Instance of 'Point'
//和其他不一样,dart有常量构造体,例如:
var immutablePoint1 = ImmutablePoint.point;
// immutablePoint1.x = 10;//修改就会报错
var immutablePoint2 = ImmutablePoint.point;
// immutablePoint2.x = 15;//修改同样会报错
//获取对象的类型
print('p对象的类型是:${p.runtimeType}'); //打印 p对象的类型是:Person
//类final成员属性的赋值方式。且实例创建之后无法修改name属性
//第一种方式
var mark = ProfileMark('张三');
print(mark.name); //打印 张三
//第二种方式
mark = ProfileMark.unname();
print(mark.name); //打印 还没设置名字哦
//dart语言特有的构造器——名字构造器
var nameConstructorPoint = Point.origin();
print(nameConstructorPoint); //打印 Instance of 'Point'
//如果父类没有名字构造器或无参构造器,那么子类就必须手动去调用父类的一个构造器,通过在
//构造器函数体后面加上冒号,再紧接父类构造函数体
var e = Employee.fromJson({});
print(e);
//构造对象e的过程先后打印
//in person
//in employee
//Instance of 'Employee'
//类中定义运算符——dart语言又一牛逼操作
var vector1 = Vector(1, 1);
var vector2 = Vector(2, 2);
var sumVector = vector1 + vector2;
print('sumVector.x = ${sumVector.x}, sumVector.y = ${sumVector.y}');
//打印 sumVector.x = 3, sumVector.y = 3
//get set关键字——可通过get set 创建额外的属性
var rectangle = Rectangle(1, 1, 10, 10);
print('rectangle.right = ${rectangle.right}'); //打印 rectangle.right = 11.0
rectangle.right = 20;
print('rectangle.left = ${rectangle.left}'); //打印 rectangle.right = 10.0
//dart又一重磅功能——类使用混合(mixin),用于类多层继承关系中,类代码重用的一种方法
//查看这几个类或mixin:Performer,Musical,Musician,Maestro。了解混合的意思。
//关键词:with,on
//with:类的后面跟随with,然后跟上定义的Mixin,例如:class ClassA with MixinA {}
var maestro = Maestro('小明');
print(maestro.canPlayPiano); //打印 false
print(maestro.canConduct); //打印 true
print(maestro.canCompose); //打印 false
//on:用于限制Mixin的使用范围,例如:Mixin MixinA on ClassA {}
//如果ClassB不继承ClassA,而是直接 with MixinA时,编译时期
//就会报错,更别说使用cb调用printSomething方法了。
var cb = ClassB();
cb.printSomething(); //打印 ---printSomething---
}
class Person {
String? name;
double? height;
int? age;
House? house;
Person({this.name, this.height, this.age, this.house});
Person.fromJson(Map json) {
print('in person');
}
}
class Employee extends Person {
//父类没有名称构造器和无参构造器时,需要手动调用父类的构造器
Employee.fromJson(Map json) : super.fromJson(json) {
print('in employee');
}
}
class Point {
num x = 0.0;
num y = 0.0;
//定义构造器的两种写法
Point(this.x, this.y); //简写方式
//标准写法
// Point(num x, num y) {
// this.x = x;
// this.y =
// }
//工厂构造函数——并不总会构造新对象,可能从缓存返回实例,也可能返回子类型实例。
factory Point.fromJson(Map<String, num> json) {
return Point(json['x'] ?? 0, json['y'] ?? 0);
}
//名字构造器
Point.origin()
: x = 0,
y = 0;
}
//不可变Point
class ImmutablePoint {
static const ImmutablePoint point = ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
class House {
String address;
House({required this.address});
}
class ProfileMark {
final String name;
ProfileMark(this.name);
//这也是一种构造方式
ProfileMark.unname() : name = '还没设置名字哦';
}
class Vector {
final int x, y;
Vector(this.x, this.y); //定义构造函数
//操作符返回类型 操作符关键字 操作符标识符
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
}
class Rectangle {
double left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
//返回值类型 关键字 属性名 => 返回值计算
double get right => left + width;
//无返回值 关键字 属性名 参数列表 => 设置属性逻辑
set right(double value) => left = value - width;
double get bottom => top + height;
set(double value) => top = value - height;
}
//表演家
class Performer {}
//音乐的
mixin Musical {
bool canPlayPiano = false; //会弹钢琴
bool canCompose = false; //会创作、作曲
bool canConduct = false; //会指挥
//招待我
void entertainMe() {
if (canPlayPiano) {
print('弹钢琴');
} else if (canConduct) {
print('指挥');
} else {
print('自言自语');
}
}
}
//音乐家
class Musician extends Performer with Musical {}
//大师
class Maestro extends Person with Musical {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
//Mixin中限制关键词on的使用
class ClassA {}
mixin MixinA on ClassA {
printSomething() {
print('---printSomething---');
}
}
class ClassB extends ClassA with MixinA {}
- 库和库的可视性
void main() {
//库和可视性
//1.导入内置库格式:impot 'dart: scheme'; //其中scheme表示格式、结构
//2.倒入第三方库
//2.1方式1) import 'package: scheme';
//2.1方式二) import '文件系统路径';
//3.如果导入的库标识符冲突,可通过库前缀解决,例如:import 'package:lib1/lib1.dart' as lib1;
//4.导入库的一部分
//4.1 import 'package:lib1/lib2.dart' show foo;//仅导入foo部分
//4.2 import 'package:lib1/lib1.dart' hide foo;//导入除foo之外的其他部分
//5.延迟加载库,使用:deferred as
//例如:import 'lib1/lib1.dart' deferred as foo;
//当要使用foo类时,需要调用loadLibrary(),可多次调用,但只会加载一次
//例如:foo.loadLibrary();
/**
使用延迟加载库时的注意点
Keep in mind the following when you use deferred loading:
1.A deferred library’s constants aren’t constants in the importing file. Remember, these constants don’t exist until the deferred library is loaded.
2.You can’t use types from a deferred library in the importing file. Instead, consider moving interface types to a library imported by both the deferred library and the importing file.
3.Dart implicitly inserts loadLibrary() into the namespace that you define using deferred as namespace. The loadLibrary() function returns a Future.
*/
}
- 异步请求
void main() {
//异步支持
//和OC和Swift很不一样,dart语言的库中,几乎所有的函数返回值都是Future或Stream对象。这些函数都是异步的,使用关键词
//async和await来支持异步编程。
//1.使用await关键词的代码,必须在被标记为async的函数中,例如:
// Future<void> checkVersion() async {
// var version = await lookUpVersion();
// }
//2.一个async函数中,可以使用多个await。(这种感觉比OC就爽太多了)
// Future someAsyncFunction() async {
// var entryPoint = await findEntryPoint();
// var exitCode = await runExecutable(entryPoint, args);
// await flushThenExit(exitCode);
// }
//3.在await表达式中,表达式的值通常是Future类型,如果不是那么这些值就是自动包装在Future中。
//4.声明异步函数(异步函数如果不需要返回值,则返回类型填写Future<void>)
Future<String> lookUpVersion() async => '1.0.0';
//5.异步请求流处理(用到再看)
}
- 生成器
void main() {
//生成器:当你需要懒加载产生一系列的值时,考虑使用一个生成器函数。
//关键词:sync*, async*, yield, yield*
//yield:产出、提供
//Dart内置支持两种生成器功能:
//1.同步生成器: 返回 Iterable 对象.例如:自然数生成
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
//简写
while (k < n) yield k++;
//标准写法
// while (k < n) {
// yield k++;
// }
}
var naturals = naturalsTo(10);
print(naturals.toString()); //打印 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
//2.异步生成器: 返回 Stream 对象.
Stream<int> asyncNaturalsTo(int n) async* {
int k = 0;
//简写
while (k < n) yield k++;
}
var asyncNaturals = asyncNaturalsTo(5);
print(asyncNaturals.toString()); //打印 Instance of '_ControllerStream<int>'
//3.递归同步生成器
Iterable<int> recursiveNaturalsTo(int n) sync* {
if (n > 0) {
yield n;
yield* recursiveNaturalsTo(n - 1);
}
}
var recursiveNaturals = recursiveNaturalsTo(8);
print(recursiveNaturals.toString());//打印 (8, 7, 6, 5, 4, 3, 2, 1)
}
- 可调用类
void main() {
//Callable classes——可以调用的类,让dart类像函数一样被调用。需要实现call()方法。
var wf = WannabeFunction();
print(wf('Hi', 'there,', 'gang')); //打印 Hi there, gang!
}
class WannabeFunction {
String call(String a, String b, String c) => '$a $b $c!';
}
- 隔离(Isolates)——用到了再学习
是一种解决多线程访问同一块内存导致错误的解决方案,详情请查看下面链接:
- Dart asynchronous programming: Isolates and event loops
- dart:isolate API reference, including Isolate.spawn() and TransferableTypedData
- Background parsing cookbook on the Flutter site
- Isolate sample app