Dart学习
=>只有一行代码可以使用剪头函数 => print(‘a’) 或者{ print(‘a’)} 内部语句后面不需要加分号其他的每个语句后面必须要加分号;
定义变量:
Dart里面是有类型校验的
一个变量没有被初始化,他的默认值就是null,比如 var a; 此时a就是null
var 可以定义任意类型,但是如果定义好了,就不能赋值为别的类型
比如var a =‘’;a = 123;会报错
String:单引号,双引号,三引号(可以写多行)
字符串拼接:print(“$str1$str2”)或者print(str1 + str2)
数值类型
int:必须是整型
double:既可以是整型,也可以是浮点型
运算符
基本算数运算符:+ - * / %(取余) ~/(取整)
关系运算符:== != > < >= <=返回值是true或者false
逻辑运算符:!(取反) && ||
赋值运算符:= ??= += -= *= /= %=~/=
??=:int a = 10;a??=23;(首先判断a是否为null,如果是null,则23赋值给a,如果不为空,不变)
条件表达式:if else、switch case、三目运算符、??运算符
switch case:判断固定值的时候比if else效率高
三目运算:c = flag==true?”我是true”:”我是false”
??:var a = 10;var b = a ?? 23;(判断a是否为null,如果是的话b为23,否则b为a的值)
类型转换
Number类型转化为String类型toString()
var str = myNum.toString();
String类型转化为Number类型int.parse()
int myNum = int.parse(str)或者double.parse(str)(最好使用double,因为如果str是double字符串的话,只能使用double.parse(),如果str是空字符串’’的话会报错,所以可以使用try{} cache(err){}
其他类型转化为bool类型
isEmpty:判断字符串是否为空if(str.isEpmty){字符串是空字符串}
Number类型:使用== if(myNum == 1 || myNum == null || myNum.isNaN){}或者其他的条件运算符
bool
true和false
条件判断
if 语句 == 判断类型以及值是否相等
数组:
List:打印后是[]
1、var list =[’123’,‘456’];list.length list[0]
2、var list = new List();list.add(‘aa’);list.add(‘bb’);
3、定义List指定类型:var list = new List();list.add(‘aa’);
常用属性:
length:长度list.length
reversed:翻转打印后是(),var newList = list.reversed.toList();转化为反转后的数组
isEmpty:是否为空list.isEmpty
isNotEmpty:是否不为空list.isNotEmpty
常用方法:
add:增加 list.add(‘aa’); 只能增加一个 修改当前数组
addAll:拼接数组list.addAll([‘aa’,‘bb’])修改当前数组
indexOf:查找传入具体值 list.indexOf(‘aa’);返回aa的索引值,查找不到返回-1
remove:删除传入具体值list.remove(‘aa’);修改当前数组
removeAt:删除传入索引值list.removeAt(1);修改当前数组
fillRange:修改list.fillRange(start,end,‘aaa’)修改当前数组List list =[‘a’,‘b’,‘c’]list.fillRange(1,3,’d’)修改之后的就是[‘a’,‘d’,‘d’]
insert(index,value):指定位置插入list.insert(0,‘d’)修改当前数组
insertAll(index,list):指定位置插入list.insert(0,[‘a’,‘b’,‘c’])
toList():其他类型转化为List
join():List转化成字符串var str = list.join(‘,’);返回字符串
split():字符串转化成List List list = str.split(‘,’);返回数组
forEach:list.forEach((value){print(value);print(“$value”);});
map:用于修改集合里面的数据List list=[1,2,3];var newList = list.map((value){return value * 2;})print(newList.toList())
where:var newList=list.where((value){return value > 2;})print(newList.toList())返回[3]
any:判断list里面有没有满足条件的数据返回bool var f=list.any((value){return value > 2;})只要集合里面有满足条件的就返回true
every:判断list里面有没有满足条件的数据返回bool var f=list.every((value){return value > 2;})集合里面所有的元素都要满足条件才返回true,否则返回false
数组截取sublist(0,3)
集合
Set:主要功能就是去除数组重复内容打印的话是{},Set是没有顺序且不能重复的集合,所以不能通过索引去获取值
var set = new Set();set.add(‘a’); set.add(‘a’);打印之后还是{‘a’}通过set.toList()可以转化为数组
通过set.addAll(list).toList()返回去重后的数组
forEach:set.forEach((value)=>{print(“$value”)});
map:同数组
where:同数组
any:同数组
every:同数组
字典
Map:key必须要加引号,定义Map也可以指定类型
1、var person = {“name”:“张三”,“age”: 12,“work”: list} person[“name”]
2、var person = new Map();person[“name”]=“里斯”;person[“age”]=12;person[“work”]=list;
常用属性
keys:获取所有的key值map.keys返回的是(),可以使用mao.keys.toList()转化为数组[]
values:获取所有的value值map.values同上
isEmpty:是否为空map.isEmpty
isNotEmpty:是否不为空map.isNotEmpty
常用方法
remove(key):删除指定key的数据map.remove(‘key’)修改当前的map
addAll({}):合并映射,给映射内增加属性map.addAll({“work”:“工作”})
containsValue:查看映射内的值返回true/false map.containsValue(“工作”);
forEach:map.forEach((key,value){print(key);print(“$value”);});
map:同数组
where:同数组
any:同数组
every:同数组
判断数据类型
is:if(str is String){} else if(str is int){} else{}
常量:
const:值不变,一开始就得赋值
final:可以开始不赋值,只能赋值一次;而final不仅有const的编译时常量的特性,最重要的是他是运行时常量,即在运行时第一次使用前才初始化。也就是可以使用final a = new DateTime.now();
循环语句
++(自增运算符) - -(自减运算符)
for:for(int i = 0;i < 10;I++){} for(var item in myList){}
while、do while
函数、方法
1、自定义方法
返回类型 方法名称(参数1,参数2,…) {}
1>可选参数
定义一个可选参数的方法:可选参数放在后面,可以有多个
String printUserInfo(String name,[int age,String work]){if(age == null){return“”;}return“姓名是$name年龄是$age工作是$work”}调用print(“你好”)
2>默认参数
定义一个默认参数的方法:可选参数放在后面,可以有多个示例,默认参数放在可选参数里面并且放在前面
String printUserInfo(String name,[int age = 30,String work]){if(age == null){return“”;}return“姓名是$name年龄是$age工作是$work”}调用print(“你好”,20)
3>命名参数
使用{},除非有默认参数,否则是必传的String printUserInfo(String name,{int age = 30,String work}){if(age == null){return“”;}return“姓名是$name年龄是$age工作是$work”}调用print(“你好”,age:20,work:”工作”)
4>把方法当参数的方法
1>>fun2(fn1);2>>匿名方法fn2((value){print(value)});
2、箭头函数
=>只有一行代码可以使用剪头函数 => print(‘a’) 或者{ print(‘a’)} 内部语句后面不需要加分号其他的每个语句后面必须要加分号;如果有return的话可以不写return,系统默认return
var newList=list.map((value)=>value>2?value*2:value)
3、匿名函数
map方法就是
var printNum =(int n){print(123);} 调用printNum(20);
4、自执行方法
((){
print(‘我是自执行方法’);
})()
((Int n){
print(‘我是自执行方法$n’);
})(12)
5、方法的递归
一个方法调用自己
var sum = 0;fn(int n){sum+=n;if(n==0){return;}. fn(n-1)}
6、闭包
全局变量:常驻内存,影响全局
局部变量:不常驻内存,会被垃圾机制回收,不影响全局
闭包:常驻内存,并且不影响全局
fn(){
var a = 123;//常驻内存,而且不影响全局
retun(){
a++;
print(a);
}
}
var b = fn();b();b();b();打印出来是124 125 126
7、类、对象
特性:封装、继承、多态
Dart所有的东西都是对象,所有的对象都继承自Object类
Dart是一门使用类和单即成的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类,一个类通常由属性和方法组成。
1>定义的类是放在main函数外面的
Person {
String _p;//私有属性
String name=“张三”;
int age=23;
void getInfo(){
print(“$name——$age”);
print(“${this,name}——${this,age}”);//推荐写法
}
void setInfo(int age){
this.age = age;
}
void _run(){
print(‘这是一个私有方法’);
}
String getP(){
//间接访问
retun this,_name;
}
//默认构造函数,在实例化的时候触发
Person(int age){
print(‘这是构造函数’);
this.age = age;
}
或者
//默认构造函数,在实例化的时候触发,需要在后面添加分号,跟上面的是一致效果
Person(this,dage);
//命名构造函数
Person.now(int age){
print(‘我是明明够构函数’);
this.age = age;
}
// getter方法,没有()
get area{
print(this.age);
return age;
}
// setter方法
set area(int value){
this.age = value;
}
}
main(){
Person p = new Person(20);
print(p.name);
p.getInfo();
p.setInfo(20);
p.area;//调用get方法
p.area = 30;//调用set方法
}
2>构造函数 如上
Dart里面构造函数可以写多个,但是默认构造函数只能写一个,命名构造函数可以写多个
3>类单独抽离成文件
直接把Person的代码写到单独文件夹
使用的时候直接引用 import ‘文件地址不用./’
4>私有属性 私有方法
首先我们需要把类抽离为单独的文件夹,其次在前面添加_ 内部使用的话也得添加_ 比如this._name;
5>类中的getter和setter方法
6>初始化列表
用于构造函数
实例化之前类的内部赋值
比如在类的内部的构造函数里面
Person():name=“张三”,age=12{}
7>静态成员
使用static 关键字来实现静态属性和静态方法
静态方法不能访问非静态成员
非静态方法可以访问静态成员:内部使用静态属性的时候直接使用属性名称name,使用非静态属性的时候最好使用this.name,访问静态方法的话直接使用getInfo()
调用静态属性和静态方法使用类名来调用Person.age;Person.setInfo();
8>操作符
? 条件运算符(了解)Person p; p?.printInfo(); 此时不能打印,如果p初始化,就能调用方法
as类型转换 var p =‘’;p = new Person();(p as Person).pringInfo();强制类型转换
Is类型判断if(p is Person)判断变量类型
.. 级联操作(连缀)记住!!!就是一下执行多个操作
Person p = new Person();
p..name=“李四”
..age=30
..printInfo();
9>类的继承
子类使用extends关键词来继承父类
子类会继承父类里面可见的属性和方法,但是不会继承构造函数
子类能复写父类的方法
class Person {
String name;
int age;
Person(this.name,this.age);
void printInfo(){
print(‘${this.name}——${this.age}’);
}
void run(){
print(‘run’);
}
}
class Web extends Person {
String sex;
//能继承父类里面的属性
//不能继承构造函数,所以需要我们自己写
//给父类的默认构造函数传参数,同时也可以给命名构造函数传参super.xxx(name,age)
Web(String name,num age,String sex): super(name,age){
this.sex = sex;
}
//复写标示符 每一个复写方法 都加一次 可写可不写,建议写
@override
//子类中复写父类的方法,调用的是子类的方法
void run(){
super.run();//调用父类方法
print(‘子类跑’);
}
}
使用:Web w = new Web(‘张三’,12,‘男’);
8、抽象类、多态、接口
1>抽象类:Dart中抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口
抽象类通过abstract 关键字来定义
Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法
如果子类继承抽象类,必须得实现里面的抽象方法
如果把抽象类当作接口实现的话必须得实现抽象类里面定义的所有属性和方法
抽象类不能被实例化,只有他的子类可以
extends和implements的区别:
如果要复用抽象类里面的方法,并且要用抽象方法约束子类的话我们就用extends继承抽象类
如果只是把抽象类当作标准的话我们就用implements实现抽象类
抽象类:是不能实例化的
abstract class Animal {
eat(); // 抽象方法,没有方法体
printInfo(){
print(‘普通方法’);
}
}
class dog extends Animal {
//必须实现
@overide
eat(){
print(‘小狗在吃骨头’);
}
}
2>多态
允许将子类类型的指针赋值给父类类型的指针,同一个函数调用会有不同的执行效果
子类的实例赋值给父类的引用
多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类都有不同的表现 如上面的抽象类的例子的Animal和Dog
3>接口
Dart也有接口
Dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作接口被实现同样适用implements关键字进行实现
如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要重新复写一边
而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现java接口那样的方式,一般使用抽象类,建议使用抽象类定义接口。
只有抽象方法,不写公用方法
abstract class Db { //当作接口接口:就是约定、规范
String uri;
add(String data);
save();
delete();
}
// 定义其他类 实现接口,必须要实现所有的方法和属性
class Mysql implements Db {
@override
String uri;
@override
add(String data){
print(data);
print(this.uri);
}
@override
save(){
}
@override
delete(){
}
Mysql(this,uri);
}
main(){
Mysql s = new Mysql(‘uri’);
s.add(‘data’);
//或者
Mysql s = new Mysql();
s.uri =‘123.123.123.123’;
s.add(‘data’);
}
9、Dart中一个类实现多个接口以及Dart中的Mixins
一个类实现多个接口
class C implements A,B {实现接口所有的属性以及方法}
Dart中的Mixins
中文意思就是混入,就是在泪中混入其他功能
在Dart中可以使用mixins实现类似多继承的功能
因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件
1>作为mixins的类只能继承自Object,不能继承其他类
2>作为mixins的类不能有构造函数
3>一个类可以mixins多个mixins类
4>mixins绝不是继承,也不是接口,而是一种全新的特性
实现类似多继承
A和B是mixins而且是普通的类,只能直接继承自Object(比如A不能继承Person类),不能有构造函数
class C with A,B {里面有A和B的所有的属性和方法}
class C extends Person with A,B{ //此时C继承自Person同时mixinsA和B
//此时Person类里面有构造函数,C类必须要实现此构造函数
C(string name,num age):super(name,age);
}
如果A和B中有同样的方法,则后面的方法替换前面的方法 比如 with A,B 调用的就是B的方法,如果是with B,A则使用的是A的方法。
如果继承中也有同样的方法,同样是后面的替换前面的
C is A以及C is B以及C is C以及C is Person都是true
10、范型 范型方法 范型类 范型接口
1>范型:解决类 接口 方法的复用性,以及对不特定数据类型的支持(类型校验)
2>范型方法:
需求,函数传入什么类型,返回什么类型,并支持类型校验,使用范型 使用T
T getData(T value){return value}对传入类型校验,以及对返回类型校验
getData(T value){return value}只对传入类型校验,不对返回类型校验
调用getData(‘你好’);检查传入类型和返回类型都是String
3>范型类:
集合List范型类的用法
List也是范型List list = new List();只能添加String的类型
案例:写一个范型类,要求List里面可以增加int类型的数据,也可以增加String类型的数据
class PrintClass<T> {
List list=new List();
void add(T value){
this.list.add(value);
}
}
使用:
要求只传入String
PrintClass p = new PrintClass();p.add(“你好”);
要求只传入int
PrintClass p = new PrintClass();p.add(123);
4>范型接口
abstract class Cache {getKey(String key);void setByKey(String key,T value)}
案例:实现功能:有文件缓存、和内存缓存,内存缓存和文件缓存按照接口的约束实现
定义一个范型接口约束实现他的子类必须有getByKey(key)和setByKey(key,value)
要求setBykey的时候的value的类型和实例化子类的时候指定的类型一致
abstract class Cache<T> {
getData();
void setByKey(String key,T value);
}
class FileCache<t> implements Cache<T> {
@override
getData(){
return null;
}
@override
void setByKey(String key,T value){
print(‘我是文件’);
}
}
class MemoryCache<T> implements Cache<T> {
@override
getData(){
return null;
}
@override
void setByKey(String key,T value){
print(‘我是缓存’);
}
}
使用
MemoryCache m = new MemoryCache();
m.setByKey(“index”,“我是首页缓存”);
11、Dart中的库 自定义库 系统库 第三方库
在Dart中,库的使用时候通过import关键字引入
library指令可以创建一个库,每一个Dart文件都是一个库,即使没有使用library指令来指定
Dart的库主要有三种:
1>我们自定义的库
import‘lib/xxx.dart’;
2>系统内置库
import‘dart:math’;
import‘dart:io’;
import‘dart:convert’;
3>Pub包管理系统中的库
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/
需要在自己项目根目录新建一个pubspec.yaml
在pubspec.yaml文件 然后配置名称、描述、依赖等信息
然后运行pub get获取包下载到本地
项目中引入库import‘package:http/http.dart’as http;看文档使用
async和await
只有async方法才能使用await关键字调用方法
如果调用别的async方法必须使用await关键字
async是让方法变成异步
await是等待异步方法执行完成
例如
void main()async {
var result = await testAsync();
}
testAsync()async {
return“hello”;
}
库冲突之后的重命名
比如Person1和Person2中都有一个Person类,则如下处理
库里面只引用部分功能
使用关键字 show 和 hide,导入库中的某一些方法
关键自part和export