我正在参加「掘金·启航计划」
开发环境
搭建Dart 开发环境:macOS为例
以下环境配置以 mac 为例
-
下载并解压 Dart SDK(版本 2.13.4)
- 下载地址:dart.cn/tools/sdk/a…
- 将 Dart SDK 解压到指定的文件目录
-
配置环境变量(保证可以访问到Dart SDK)
sudo vim ~/.zshrc
#指定 Dart SDk 安装路径 export PATH="$PATH:/Users/whp/SDK/dart-sdk/bin #找到隐藏的配置文件 刷新配置 source ~/.zshrc
-
检查 是否安装成功 (查看Dart SDk版本)
dart --versin
常量
常量:用于记录不可以修改的数据
const a=10
final b=28
区别
- const是编译期常量,用于记录程序在编译期就要能确定的值
- final 是运行时常量,用于记录程序在运行时确定的值
数据类型
var 关键字定义不同的类型,并且有类型推断的检查
Dart 空安全机制
-
在空安全机制下,代码中的类型
默认都是非空
的除非将变量明确的声明为可空,否则它一定是非空的类型
-
作用:原本处于运行时的空值引用错误,将变为编译时的分析错误,从而bug会发现的更早
-
空安全机制下,如何定义并使用变量?
- 变量不能为空时:指定默认值
- 变量可以为空时:使用 " ?" 明确的指定变量可以为空
常用的数据类型
-
num (数值)
-
num ( 整数或浮点数 )
num n1=10 print(n1) // 10 n1=10.1 print(n1) // 10.1
-
int (整数)
int n2=20 n2=20.1 //报错
-
double (浮点数)
double n3=30.1 print(n3)// 30.1 n3 =30 print(n3)// 30.0
-
-
bool (布尔)
bool 类型用于记录真或假 ,一般用于逻辑判断
-
StrIng (字符串)
-
定义字符串:String
String name='itcast'
-
拼接字符串
//插值表达式:'${表达式}'或'$变量" double price=9.0 String priceStr=‘$price起'
-
注意点:使用 + 拼接字符串时,只能 “字符串+ ”字符串“
double price=9.9 String priceStr= price +'起' //报错
-
-
LIst (列表)
-
定义列表 :List
List categories=["居家","美食",”服饰]
-
使用
-
列表长度:列表 length
-
查询:列表[角标]
-
修改:列表[角标]=新值
-
新增:
新增一个元素:列表add (新增)
新增一个列表:列表addAll (新增列表)
-
删除:
删除指定的元素:remove(元素) 或者removeA(角标)
-
遍历列表
列表forEach()
-
-
-
Map (字典)
Map(字典)是使用键值对存储数据的
语法:(key:value)
-
定义字典
Map category ={ 'id':'1', 'name';'居家' }
-
使用字典:查改增删
- 查询 : 字典(key]
- 修改: 字典[key]=新值
- 删除:字典 remove(key)
- 新增( 不常用): 字典【新key】=新值 (注意:新key 必须是不存在的key)
-
遍历字典:字典 forEach()
-
-
函数
函数定义
-
Dart 函数的结构
返回值类型 函数名(参数1,参数2){ 函数体 return 返回值; }
-
调用函数
函数(参数1,参数2)
-
示例:定义计算任意两个整数之和的函数,并返回计算结果
int sum(inta,intb){ int ret=a+b return ret } int ret=sum(10,20) print(ret) //30
-
返回值 类型和参数类型都可以省略
// 返回值类型参数类型都可以省略 sum2(a,b){ int ret =a+b return ret } int ret= sum2(10,20) print(ret)//30
-
函数都有返回值,如果没有明确指定,默认返回
null
//函数都有返回值,如果不指定返回值类型,默认返回 null sum1(){ int ret=1+2 print(ret) } print(sum1())//null
可选命名参数
-
可选命名参数
注意
:可选参数必须是可以为空的返回值类型 函数名(参数1,参数2,....,{可选参数1?,可选参数2?,....}){ 函数体 return 返回值; }
-
默认参数
返回值类型 函数名(参数1,参数2,..., {可选参数1?=默认值1,可选参数2?=默认值2}){ 函数体 return 返回值; }
函数对象
在Dart中,一切都是对象,函数也是对象,类型是Function
-
函数可作为对象赋值给其他变量
void funDemo1(){ print("funcDemo1") } Function f=funcDemo1 f()//funcDemo1
-
函数可作为参数传递给其他函数
//该函数接收一个函数作为参数 void funcDemo2(Function func){ func() } //作为参数的函数 void funcDemo3(){ Print("funcDemo3") } //把函数 funcDemo3当参数传给funcDemo2 funcDemo2(funcDemo3)//funcDemo3
箭头函数
函数体只包含一个表达式时,可以使用箭头函数进行简写
提示:=>表达式 是对 {return 表达式} 的简写
int sum(int a,int b){
return a+b
}
sum(10,20)
//简写
int sum(int a,int b)=> a+b;
匿名函数
匿名函数是一种没有函数名称的 函数
但是和其他函数 一样,它也有形参列表,也可以有可选参数
(参数1,参数2,...){
函数体
return 返回值;
}
特点:仅在调用时,才临时创建函数对象,调用完立即释放,节省内存空间
-
可赋值给变量,通过变量进行调用
//定义匿名函数赋值给变量并调用 Function f=(String name){ print(name) } f("itcast");//itcast
-
可当做参数传递给其他函数去调用(回调函数)
//匿名函数当做参数传递给其他函数 demo((){ print("匿名函数当做参数") })
类
类的定义
使用 class 关键字声明一个类,所有的类都是继承自 Objecto 类
类的组成:属性 和 方法
属性和方法都是通过,访问的
例子:定义一个Person类,属性是名字和年龄,方法是吃饭
class Person{
//属性:名字、年龄
String? name;
int? age;
//方法:吃饭
void eat(){
print('我是干饭人')
}
}
//创建Person对象
Person person=Person();
// 设置Person对象
person.name='张三'
person.age=18;
print(`我叫${person.name} 今年${person.age}`)
person.eat();//我是干饭人
构造函数
创建对象时调用的函数,常用的构造函数有:
-
类名构造函数
-
默认构造函数(无参数,默认隐藏)
class Person { // 默认构造函数 (与类同名,无参数,默认隐藏) Person(){ print("这是默认的构造函数") } //... }
-
-
自定义类名构造函数(可以有参数)
注意点:类名构造函数,只能有一个,如果自定义了类名构造函数,那么默认的类名构造函数就无效了
//自定义与类同名的构造函数(有参数) Person(String name,int age){ this.name=name this.age=age }
//简写:参数名同属性名时,可以简写 Person(this.name,this.age) //使用自定义与类同名的构造函数创建Person对象 Person person=Person('李四',18)
-
命名构造函数
命名构造函数,可以为类提供多个不同的构造函数
-
定义方式:类名.函数名(){}
//命名构造函数 Person.withName(String name){ this.name=name; } //简写命名构造函数 Person.withName(this.name); //使用命名构造函数创建Person对象 Person person=Person.withName('王五');
-
-
工厂构造函数
工厂构造函数,不会直接创建对象,而是在构造函数内部通过代码来决定要创建的对象
-
定义方式:使用
factory
关键字声明工厂构造函数//工厂构造函数 factory Person.withInfo(String name,int age){ return Person(name,age) } //使用工厂构造函数创建Person对象 Person person=Person.witInfo("李雷",18)
-
-
使用场景:当需要根据条件来决定要返回的对象时,比如:单例
//工厂构造函数 factory Person.withInfo(String name,int age){ //如果age<0,Person对象默认都是0岁 return age<0 ? Person(name,0):Person(name,age) } //使用工厂构造函数创建Person对象 Person person=Person.withInfo("李雷",-18)
-
私有属性和方法
-
私有属性和方法
在类中定义,不对外暴露,
不能被 其他Dart文件访问
的属性和方法 -
如何定义私有属性和方法
使用
_
定义属性和方法class Dag{ String? name; // 私有属性 int? _age; void eat(){ print('dag eat') } //私有方法 void _run(){ print('dog run') } } Dog dog=Dog() dog.name='旺财' print(dog.name); // dog._age;//在其他Dart文件无法调用私有属性 dog.eat() //dog._run();//在其他Dart文件无法调用私有方法
-
继承
通过继承可以让子类拥有父类的一些属性和方法
-
如何实现继承
子类使用
extends
关键字继承父类 -
继承的特点
- Dart的继承是单继承,一个子类只能有一个父类
- 子类只会继承父类里面可见的属性和方法,不会继承私有属性和方法
- 子类只会继承父类默认的构造函数,不会继承 其他构造函数
- 子类可以重写父类的方法,也可以使用super 调用父类方法
mixin
-
mixin 可以理解为扩展类
- 可以为类扩展功能 ,而不需要使用继承,类似Vue里面的混入
-
如何定义mixin
- 定义:mixin关键字
//定义mixin类 mixin WalkMixin{ double? speed; void walk(){ print('walk') } }
- 使用:with 关键字
//人,吃饭和走路 class Person extends Animal with WalkMixin{ }
-
mixin的特点
- 可以扩展属性和方法
- 不能被实例化,不能被继承
异步编程
能够使用 Dart
异步编程解决耗时操作阻塞程序的问题
- 在Web端和App中,有很多耗时操作都需要异步执行
Web端
的异步解决方案是 Promise,再配合 async -await 更能以同步的方式编写异步代码- Dart也同样提供了异步解决方案 Future,也可以配合async -await 使用
Future
Future是一个表示 延迟计算的对象。代表一些计算将异步进行
Future会在耗时操作执行完毕前直接返回,而不会等待耗时操作执行结束
例子:模拟耗时听任阻塞程序,并使Future
解决程序阻塞问题
注意:Future配合
async
-await
以同步的方式编写异步代码
print("开始喽")
Future((){
//指定时间阻塞5s 模拟耗时操作
sleep(Duration(seconds:5));
return '模拟返回异步任务执行的结果'
}).then((value){
//监听耗时操作执行结束
print(value)
}).catchError((onError){
//捕获异步的异常
print(onError)
})
print("假如这是一个不能等待的任务")
dynamic 类型
- 在Dart中,虽然有类型推断和类型检查
- 但是,还可以使用
dynamic
关键字关闭变量的类型检查
-
特点
- 编码灵活,可以保存任意类型的数据
- 容易产生
NoSuchMethodError
的异常
泛型
泛型是指类型的不确定性,数据具体的类型可以在使用时确定
-
使用泛型可以限定类型
-
使用泛型可以明确约束列表元素的类型
List<String>categories=['居家','美食','100']
-
-
使用泛型可以明确约束字典的key和value的类型
Map<String,String> category={ 'id':'1', 'name':'居家' }
-
使用泛型可以减少重复代码
//泛型函数 T demo<T>(T value){ return value; } // 使用泛型函数 String ret=demo<String>("itcast'); print(ret)
异常
-
如何捕获异常
-
使用关键字 try catch捕获并处理异常
-
finally
:无论是否有异常都会执行到的语句块void main{ try{ dynamic name='itheima' }catch(e){ print(e } finally { print('finally') } }
-
-
如何手动抛出异常:使用关键字
throw
手动抛出异常try { if(str!='itheima'){ throw 'str 内容跟 itheima不匹配'; } }catch(e){ print(e) }