dart其他语法
https://www.wenjiangs.com/doc/4rjgb53a
类型相关
空安全
不能将一个普通类型对象赋值为 null
- 避免 为空 报错:对 null 的使用语法进行限制(str != null)
- 对空安全的允诺
late 延迟初始化的时机
! 在此时该可用变量一定不为空
void main() {
String name = 'zhang';
say(name);
String? xm = null; // 可空的字符串
try {
say(xm!); // ! 在此时该可用变量一定不为空
} catch (e) {
print(e);
}
}
void say(String str) {
late String name; // 承诺 name 不为空,先定义
if (str == null) {
throw Exception('Invalid string');
}
print('my name: $str ,has ${str.length} characters');
}
类定义相关语法
- 类的运算符重载
就是个参数固定,名称特殊的函数而已。
class Vec2 {
double x, y;
Vec2(this.x, this.y);
// operator 关键字加上 运算符 作为方法名即可
// 加法是二元运算符,所以方法中有一个入参。该入参类型就是使用时 + 后面的对象类型
// 开头 Vec2 依然表示返回类型
Vec2 operator +(Vec2 other) => Vec2(x + other.x, y + other.y);
// 接收一个 入参是布尔值的列表,返回一个浮点数
double operator [](bool flag) => flag ? x : y;
String toString() {
return 'Vec2(x: $x, y: $y)';
}
}
void main() {
Vec2 v1 = Vec2(1, 2);
Vec2 v2 = Vec2(3, 4);
double val = v1[true];
print((v1 + v2).toString());
print(val);
}
- 类的扩展方法
支持在某类定义文件之外,拓展该类的方法,在其中可以访问类成员
相当于 js 在原型上添加方法
extension A on B 来定义,其中 A 的名字是任意的,B 是拓展的目标类
不能在拓展在原类中已存在的方法
// A相当于 string的一个成员方法,可以访问this对象
extension A on String {
String isANullString() {
// ignore: unnecessary_this
if (this.trim() == '') {
return 'yes';
} else {
return 'no';
}
}
bool isPhone() {
RegExp regExp = RegExp(r'^1[34578]\d{9}$');
return regExp.hasMatch(this);
}
// 运算符本身也是一种方法,支持扩展
// 判断配个 String 首位字符的大小
bool operator >(String other) {
int thisCode = 0;
int otherCode = 0;
if (isNotEmpty) {
// 相当于this.
thisCode = codeUnits.first; // 相当于this.
print(thisCode);
}
if (other.isNotEmpty) {
otherCode = other.codeUnits.first;
print(otherCode);
}
return thisCode > otherCode;
}
}
void main() {
String str = ' ';
String res = str.isANullString();
print(res);
String str1 = '13550256060a';
bool res1 = str1.isPhone();
print(res1);
String str2 = 'hello';
String str3 = 'nihao';
bool res2 = str2 > str3;
print(res2);
}
- 几个符号介绍
… 可以实现连续的调用
… 用于解构可迭代对象
class Person {
String name = '';
int age = 0;
void log() {
print("name:$name,age:$age");
}
}
void main() {
Person toly = Person();
// toly.name = "toly";
// toly.age = 28;
// toly.log();
// .. 可以实现连续的调用,等价于上面三行,语法糖而已
toly
..name = "toly"
..age = 28
..log();
// ... 用于解构可迭代对象
List list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
List list2 = [0, ...list, 100];
print(list2);
}
- enum 枚举
enum GenderType { male, female, secrecy }
String ShowInfoByGender(GenderType type) {
switch (type) {
case GenderType.male:
return "男性";
case GenderType.female:
return "女性";
case GenderType.secrecy:
return "保密";
}
}
void main() {
GenderType type = GenderType.male;
// List<GenderType> li = GenderType.values;
// print(li); // [GenderType.male, GenderType.female, GenderType.secrecy]
String res = ShowInfoByGender(type);
print(res);
}
函数类型的回调与监听
通过 typedef 来定义一个函数类型
typedef OperateNumFun = int Function(int num1, int num2);
void main() {
// addNumFun 是 OperateNumFun 函数类型
OperateNumFun addNumFun = (num1, num2) {
return num1 + num2;
};
OperateNumFun plusNumFun = (num1, num2) {
return num1 * num2;
};
print(addNumFun(1, 2));
print(plusNumFun(1, 2));
print(plusNumFun.runtimeType); // (int, int) => int
}
- 高级用法
typedef OnBiteCallBack = void Function(String name);
// 函数作为参数传入到类的构造函数中
// 通过回调与监听,可以为不同类之间 事件触发 和 数据传递 提供一种机制
class FishMan {
final OnBiteCallBack hook;
FishMan({required this.hook});
}
class Pond {
FishMan fishMan;
Pond({required this.fishMan});
void emitFish(String name) {
fishMan.hook(name);
}
}
main() {
FishMan man = FishMan(hook: (String name) {
print("钓到一条$name");
});
Pond pond = Pond(fishMan: man);
pond.emitFish("鲫鱼");
}
语法相关
异步中的 Future 对象
- 异步任务与回调
// Future 中有一个 then 方法,用于监听异步任务的完成
// 通过 async 声明异步,await等待 Future对象执行完成
import "dart:io";
import "package:path/path.dart" as path;
void main() async {
File file = File(path.join(Directory.current.path, "../one.iml"));
// file.readAsString().then((value) => print(value));
String value = await file.readAsString();
print(value);
}
- Stream 对象
Future 对象是一件异步任务,那么 Stream 则是一系列的异步任务
它可以监听到若干次回调
// stream(params1,params2)
// params1 :每次读取到数据,都会触发 params1 方法
// params2 用于监听读取完毕的事件
// Stream#listen 方法会返回一个 StreamSubscription 的订阅对象
// subscription.cancel 方法取消监听
// subscription.pause(); 暂停监听
// subscription.resume(); 恢复监听
import 'dart:io';
import "package:path/path.dart" as path;
class ReadFile {
int fileLength = 0;
int count = 0;
late dynamic subscription;
void taskOne() async {
File file = File(path.join(Directory.current.path, '../web/index.html'));
fileLength = await file.length();
print('开始读取文件');
Stream<List<int>> stream = file.openRead();
subscription = stream.listen(taskTwo, onDone: complete);
}
void taskTwo(List<int> bytes) {
count += bytes.length;
double percentage = count * 100 / fileLength;
DateTime time = DateTime.now();
String timestr =
'${time.hour}:${time.minute}:${time.second}:${time.microsecond}';
print('当前进度:' +
timestr +
"=" * (percentage ~/ 2) +
'${percentage.toStringAsFixed(2)}%');
if (percentage < 50) {
subscription.cancel();
}
}
void complete() {
print('读取完毕');
}
}
void main() {
var task = new ReadFile();
task.taskOne();
}
文件管理
- 文件内容的显隐: show 与 hide
被引用文件,如果建立私有方法或者变量,下划线开头,外部即访问不到
如果 定义被引用文件可访问的变量 方法,可使用 show和hide约定
// a.dart
void say(String str) {
print('this is ' + str);
}
double age = 20;
String name = '张山';
String hobby = 'read 、sing';
String _address = '武汉市xxxx';
void _hello(String str) {
print('hello ' + str);
}
// import './h.dart' as helpers hide hobby; // 基文件 中变量hobby无法访问
import './a.dart' as helpers show name, say, age; // 允许访问 name, say, age
void main() {
helpers.say('你好');
// helpers._hello('你好'); 基文件下划线开头的方法无法访问
print(helpers.age);
// print(helpers._address); 基文件下划线变量无法访问
// print(helpers.hobby); 报错
print(helpers.name);
}
- 部分与整体: part of 与 part
通过 part 关键字表示指定文件是当前文件的一部分。另外在部分的文件中使用 part of 关键字表示归属关系
// 宿主文件 g.dart
import 'dart:io'; // 给寄生文件用
part './h.dart'; // 表示 h.dart是当前文件一部分
void main() {
say('你好');
print('$_address'); // $_访问 私有方法 变量
print(_address); // 直接访问
print(name);
_hello('你好');
}
// h.dart
// 只能在宿主文件中 import引入 当前需要的第三方文件库
part of './g.dart'; // 表示当前文件是 g.dart 文件一部分
void say(String str) {
print('this is ' + str);
print('当前路径是:${Directory.current.path}/g.dart');
}
double age = 20;
String name = '张山';
String hobby = 'read 、sing';
String _address = '武汉市xxxx';
void _hello(String str) {
print('hello ' + str);
}
- 定义库与导出: library 与 export
使用 library 关键字定义库名,export 关键字导出相关文件
// m.dart
void logTime() {
var time = DateTime.now();
String str = '${time.hour}:${time.minute}:${time.second}';
print(str);
}
// h.dart
import 'dart:io';
void say(String str) {
print('当前路径是:${Directory.current.path}/g.dart');
}
// helper_lib.dart
export './m.dart';
export './h.dart';
import 'helper_lib.dart' as Helper;
void main() {
Helper.logTime();
Helper.say('string');
}