Dart知识点汇总

1.数据类型

/*
Dart 变量:
        dart 是一个强大的脚本语言, 可以不预先定义变量类型, 自动会类型推导.
        dart中定义变量可以通过var关键字/类型来声明变量.
        如:
        var str = 'this is var';
        String str = 'this is var';
        int str = 123;
    注意: var 后面不要写类型, 写了类型就不要var, 两者都写会报错.

Dart 常量: final 和 const修饰符
        const值不变, 一开始就得赋值
        final可以开始不赋值, 只能赋一次; 这是两者的差别.
        
        永远不改变的量, 请使用final或const修饰它,而不是使用var或其他变量类型.
        
Dart的变量命名规则:
        1.变量名称必须由数字、字母、下划线和美元符($)组成
        2.注意: 标识符开头不能是数字
        3.标识符不能是保留字和关键字
        4.变量的名字区分大小写的如: age和Age是不同的变量, 在实际的运用中, 也建议, 不要用一个
        5.标识符(变量名称)一定要见名思意: 变量名称建议用名词.方法名称建议用动词.
*/

2.字符串类型

//定义字符串
var a = '''
你好啊
你好啊
''';
String b = "不错";
final c = 'Dart';

// 字符串拼接
print("$a $b $c");
print(a +b+c);

3.list集合类型

//第一种定义list方式
var l1 = ['aaa','bbb','ccc'];
print(l1.length);
//第二种定义list方式
var l2 = new List();
l2.add('张三');//拼接数组
l2.add('李四');
print(l2[1]);

//定义List指定类型
var l3 = new List();

4.map类型

//第一种定义 Maps的方式
var person = {
  "name":"张三",
  "age":20
}
print(person['name']);
// 第二种定义 Maps的方式
var p = new Map();
p["name"] = '李四';
print(p);

5.类型判断

//is 关键字来判断类型
if(str is String){
  
}else if(str is int){
  
}

6.布尔类型

true false ==

7.运算符 条件判断语句 类型转换

/*Dart运算符:
算术运算符:
    +       -       *       /       ~/ (取整)     % (取余)
    
关系运算符:
    ==      !=      <       >       >=      <=
    
逻辑运算符:
    !       &&      ||
    
赋值运算符:
    基础赋值运算符     =       ??=
            b??=23; 表示如果b为空的话, 把23赋给b
    复合赋值运算符     +=  -=  *=      /=      %=  ~/=
    
条件表达式:
    if else         switch case     三目运算符           ??运算符
            String c=flag?'我是true':'我是false';
            var b = a??10; // 表示a为空的话, 把10赋值给b
*/

/*类型转换
1.Number 与 String类型之间的转换
        Number-->String, 用toString()关键词;
            
        String-->Number, 用parse关键词
                var myNum = double.parse(str);
                print(myNum is double);
                
        String price = '';
        try{//防报错
                var myNum =double.parse(price);
                print(myNum is double);
        }catch(err){
                print(0);
        }
        
2.其他类型转换成Booleans类型
        // isEmpty: 判断字符串是否为空
        var str = '123';
        if(str.isEmpty){
                print('str空');
        }
        
        var myNum;
        if(myNum==null){
            print('空');
        }
        
        var myNum = 19.9
        if(myNum==0){
            print('0');
        }
        
        var myNum =0/0;
        if(myNmu.isNaN){
                print('Nan');
        }
*/

8.++ --

var a =10
var b = --a //先运算再赋值
print(a);//9
print(b);//9

var a =10
var b =a--//先赋值再运算
print(a); //9
print(b); //10
/*
++  --  表示自增 自减 1
在赋值运算里面, 如果++  --写在前面, 这时候先运算再赋值,如果++ --写在后面, 那么先赋值再运算
*/

9.while、do...while

/*
语法格式:
    while(表示式/循环条件){
    }
    
    do{
        语句/循环体
    }while(表达式/循环体);
    
    注意: 1、最后的分号不要忘记; 
                2、循环条件中使用的变量需要经过初始化
                3、循环体重, 应有结束循环的条件,否则会造成死循环.
*/
int i=1;
while(i<=10){
  print(i);
  i++;
}


int i=1;
var sum=0;
do{
  sum+=1;
  i++;
}while(i<=100);

//while和do while的区别: 第一次循环条件不成立的情况下
int i =10
while(i<2){
  print('执行代码');
};

var j=10;
do{
  print('执行代码');//不管条件成不成立,会先执行这里的代码.
}while(j<2);

10.break和continue

/*
continue可以用在for循环以及while循环汇总, 但是不建议用在while循环中, 不小心容易死循环.

continue //跳过当前循环体,然后循环还会继续执行;
break //跳出循环体, 只能向外跳出一层;
*/
for(var i=0;i<5;i++){
  print('外层--$i');
  for(var j=0;j<3;j++){
    if(j==1){
      break;
    }
    print('里层$j');
  }
}
/*
break可以在switch case中, 也可以在for循环和while循环中
*/

11.list里面常用的属性和方法:

/*
常用属性:
    length          长度
    reversed        反转
    isEmpty         是否为空
    isNotEmpty  是否不为空
    
常用方法:
    add             增加
    addAll      拼接数组
    indexOf     查找  传入具体值       (找不到返回-1)
    remove      删除  传入具体值
    removeAt    删除  传入索引值
    fillRange   修改          
    insert(index,value);        指定位置插入
    insertAll(index,list);  指定位置插入List
    toList()    其他类型转成List
    join()      List转换成字符串
    split()     字符串转化成List
    forEach
    map
    where
    any
    every
*/
List myList =['香蕉','苹果','西瓜'];

myList.fillRange(1,3,'aaa');//把1-3的值改为'aaa'. 打印: ['香蕉','aaa','bbb'], 不会数组越界

var str = myList.join('-');//list转换成字符串
print(str);//香蕉-苹果-西瓜

var list = str.split('-');//字符串转list,   分割字符

List myList = ['香蕉','苹果','西瓜','苹果','西瓜','苹果','西瓜','苹果','西瓜',];
var s = new Set();// 通过set集合类去重
s.addAll(myList);// 元素去重
print(s);
print(s.toList());// 返回去重后的数据

12.映射(Map)是无序的键值对:

/*
常用属性:
    keys                获取所有的key值
    values          获取所有的value值
    isEmpty         是否为空
    isNotEmpty  是否不为空

常用方法:
    remove(key)     删除指定key的数据
    addAll({...})   合并映射    给映射内增加属性
    containsValue   查看映射内的值, 返回true/false
    forEach
    map
    where
    any
    every
*/
void main(){
  var person={
    "name":"张三",
    "age":20
  };
  print(person.keys.toList());// [张三, 20]
}

/*forEach、map、where、any、every 通用list、Map、set*/
//forEach循环
myList.forEach((value){
    print("$value");
});

List myList=[1,3,4];
var newList=myList.map((value){
  return value*2;//每一项值乘2,返回新集合
});
print(newList.toList());//转数组

List myList=[1,3,4,5,6,7,8,9];
var newList=myList.where((value){//where把满足条件的返回一个新集合
  return value>5;
});
print(newList.toList());//转数组

List myList=[1,3,4,5,6,7,8,9];
var newList=myList.any((value){//any:只要集合里有一个满足条件的就返回true
  return value>5;
});
print(f);//true

List myList=[1,3,4,5,6,7,8,9];
var newList=myList.every((value){//every:集合里每一个满足条件的就返回true
  return value>5;
});
print(f);//false

13.Dart方法的定义、函数的定义、可选参数、默认参数、匿名函数

/*
自定义方法:
        自定义方法的基本格式:
            返回类型 方法名称 (参数1, 参数2,...){
                    方法体
                    return 返回值;
            }
*/
// 定义一个带默认参数的方法
int sumNum(int n=20){
  var sum=0;
  for(var i=1;i<=n;i++){
    sum+=i;
  }
  return sum;
}
var n1=sumNum(5);
print(n1);
var n2=sumNum(100);
print(n2);

// 定义一个带可选参数的方法
String printUserInfo(String username, [int age]){ //行参
  if(age!=null){
    return "姓名:$username---年龄:$age";
  }
  return "姓名:$username---年龄:保密";
}
print(printUserInfo('张三',20));//实参

// 定义一个命名参数
String printUserInfo(String username, {int age, String sex='男'}){ 
  if(age!=null){
    return "姓名:$username---年龄:$age";
  }
  return "姓名:$username---年龄:保密";
}
print(printUserInfo('张三', age:20, sex:'未知'));//命名要与定义时统一

// 实现一个把方法当做参数的方法
fn1(){
  print('fn1');
}
fn2(fn){
  fn();
}
fn2(fn1);//把fn1当参数传入fn2


var fn=(){
  print('我是一个匿名函数');
};
fn();

14.Dart中的函数、箭头函数、匿名函数、闭包等

/*箭头函数: 表达式代码只能写一行*/
// 写法一:
list.forEach((value)=>print(value));
// 写法二:
list.forEach((value)=>{
  print(value)//不能写;号, 只能写一句话
});

/*匿名方法*/
var printNum=(int n){
  print(n+2);
};
printNum(12);

/*自执行方法*/
((n){
  print(n);
  print('我是自执行方法')
})(12);

/*方法的递归*/
var sum =1;
fn(n){
  sum*=n
  if(n==1){
    return;
  }
  fn(n-1);//自己调自己
}
fn(5);
print(sum);//120


/*闭包
    1. 全局变量的特点: 全局变量常驻内存、全局变量污染全局
    2. 局部变量特点: 不常驻内存会被垃圾机制回收、不会污染全局

//想实现功能: 常驻内存, 且不污染全局
    闭包: 函数嵌套函数, 内部函数会调用外部函数的变量或参数, 变量或参数不会被系统释放
    闭包写法: 函数嵌套函数, 并return里面的函数, 这样就形成了闭包
*/
fn(){
  var a=123;/*不会污染全局, 常驻内存*/
  return(){
    a++;
    print(a);
  }
}
var b = fn();
b();//124
b();//125

15.Dart中的对象 类 类的创建 构造函数 命名构造函数

/*
面向对象编程(OOP)的三个基本特征是: 封装、继承、多态
    封装: 封装是对象和类概念的主要特征. 封装, 把客观事物封装成抽象的类, 并且把自己的部分属性和方法提供给其他对象...
    继承: 面向对象编程(OOP)语言的一个主要功能就是继承, 继承是指这样一种能力: 它可以使用现有类的功能, 并在...
    多态: 允许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行效果.
    
Dart所有的东西都是对象, 所有的对象都继承自Object类.

Dart是一门使用类和单继承的面向对象的语言, 所有的对象都是类的实例, 并且所有的类都是Object的子类

一个类通常由属性和方法组成.
*/
class Person{
  String name="张三";
  int age;
  //默认构造函数
  Person(String name, int age){
    print('这是构造函数里面的内容 这个方法在实例化的时候触发');
    this.name=name;
    this.age=age;
  }
  //默认构造函数的简写
  Person(this.name, this.age);//默认构造函数只能写一个
  //命名构造函数
  Person.now(){//命名构造函数可以写多个
    print('我是命名构造函数');
  }
  Person.setInfo(String name,int age){//命名构造函数可以写多个
    this.name=name;
    this.age=age;
  }
  
  void getInfo(){
    // print("$name----$age");
    print("$(this.name)----$(this.age)");//推荐写法
  }
  void setInfo(int age){
    this.age =age;
  }
}
void main(){
  //实例化:方式一
  var p1=new Person();
  print(p1.name);
  p1.getInfo();
  
  //实例化:方式二
  Person p1=new Person();
  p1.setInfo(28);
  p1.getInfo();
  
  //实例化:方式三-通过构造函数
  Person p1=new Person('张三',20);
  p1.getInfo();
  
  //实例化: 方式四-通过命名构造函数
  Person p1=new Person.now(); //我是命名构造函数
}

16.类模块化 私有属性 私有方法

/*
Dart和其他面向对象语言不一样, Dart中没有public private protected这些访问修饰符
但我们可以使用_把一个属性或方法定义成私有.
必须把类抽离成一个文件,私有属性才有效,被外界访问到.
*/
// 在Animal.dart中
class Animal{
  String _name;
  int age;
  Animal(this._name, this.age);
  void printInfo(){
   print("$(this._name)----$(this.age)"); 
  }
  String getName(){//通过公有方法间接获取私有属性
    return this._name;
  }
  void _run(){
    print('这是一个私有方法');
  }
  execRun(){
    this._run();//类里面方法的相互调用
  }
}
//在main.dart中:
import 'lib/Animal.dart';
void main(){
  Animal a=new Animal('小狗',3);
  print(a._name);//报错
  print(a.getName());
  a.execRun();//间接调用私有方法
}

17.类中的getter和setter方法

class Rect{
  num height;
  num width;
  Rect(this.height, this.width);
  area(){
    return this.height*this.width;
  }
}
void main(){
  Rect r=new Rect(10,4);
  print("面积:${r.area()}");
}

//getter setter写法:
class Rect{
  num height;
  num width;
  Rect(this.height, this.width);
  get area{//getter方法: 计算属性
    return this.height*this.width;
  }
  set areaHeight(value){//setter方法: 计算属性
    this.height=value;
  }
}
void main(){
  Rect r=new Rect(10,4);
  r.areaHeight=6;
  print("面积:${r.area}");//注意调用直接通过访问属性的方法
}

18.类中的初始化列表

class Rect{
  int height;
  int width;
  //初始化列表
  Rect():height=2,width=10{//实例化之前做一些操作,先赋值再执行构造函数
    print("$(this.height)---$(this.width)");
  }
}
void main(){
  Rect r=new Rect();//实例化的时候动态给它赋值
}

19.Dart中的类 静态成员 操作符 类的继承

/*
Dart中的静态成员:
    1. 使用static关键字来实现类级别的变量和函数
    2. 静态方法不能访问非静态成员, 非静态方法可以访问静态成员
*/
class Person {
  static String name = "张三";
  int age=20;
  static void show(){
    print(name);
  }
  static void printUserInfo(){//静态方法
    print(name);    //访问静态属性
    show();             //访问静态方法
  }
  void printInfo(){
    print(name);        //访问静态属性
    print(this.age);//访问非静态属性
    show();                 //调用静态方法
  }
}
main(){
  print(Person.name);
  Person.show();
  Person.printUserInfo();
}

/*Dart中对象操作符:
    ?       条件运算符   (了解) 
    as  类型转换 (多用于继承和多态)
    is  类型判断
    ... 级联操作    (连缀)
*/
class Person {
    String name;
    num age;
    Person(this.name, this.age);
    void printInfo(){
      print("${this.name}---${this.age}");
    }
}
main(){
    Person p;
    p?.printInfo();//p为空,则不执行调用方法

    Person p = new Person('张三',20);
    p?.printInfo();//p为非空,执行调用方法

    if(p is Person){ //判断p对象是否属于Person类型
      p.name = "李四";
    }
    p.printInfo();
  
    var p1;
    p1='';
    p1=new person('张三',20);
    (p1 as Person).printInfo();//把p1强制转换为Person对象
  
    /// 级联操作例子:
    p1.name = '张三333';
    p1.age=40;
    p1.printInfo();
    //用级联来简写:(连缀操作)
    p1..name="李四"
      ..age=30
      ..printInfo();
}

20.Dart中的类的继承

/*Dart中的类的继承:
    1、子类使用extends关键词来继承父类;
    2、子类会继承父类里面可见的属性和方法, 但是不会继承构造函数;
    3、子类能复写父类的方法 getter和setter
*/
class Person {
  String name='张三';
  num age=20;
  void printInfo(){
    print("${this.name}--${this.age}");
  }
}
class Web extends Person{//子类继承父类

}
main(){
  Person p=new Person()
  p.printInfo();
    
  Web w=new Web();
  print(w.name);
  w.printInfo();//调用父类方法
}
/*使用super关键词, 给父类构造函数传参*/
class Person {
  String name;
  num age;
  Person(this.name,this.age);
  void printInfo(){
    print("${this.name}--${this.age}");
  }
}
class Web extends Person{//子类继承父类
  String sex;
  web(string name, num age, String sex) : super(name, age){//通过初始化列表,执行子类构造函数之前, 把子类的name和age赋值给父类的构造函数
    this.sex=sex;
  }
  run(){
    print("${this.name}--${this.age}--${this.sex}");
  }
}
main(){
  Person p=new Person('李四',20)
  p.printInfo();
    
  Web w=new Web('张三',12,'男');
  w.printInfo();//调用父类方法
  w.run();//调用子类方法
}
/*给父类匿名构造函数传参*/
class Person {
  String name;
  num age;
  Person(this.name,this.age);
  Person.xxx(this.name,this.age);
  void printInfo(){
    print("${this.name}--${this.age}");
  }
}
class Web extends Person{
  String sex;
  web(string name, num age, String sex) : super.xxx(name, age){//给父类匿名构造函数传参
    this.sex=sex;
  }
  run(){
    print("${this.name}--${this.age}--${this.sex}");
  }
}
main(){
  Person p=new Person('李四',20)
  p.printInfo();
    
  Web w=new Web('张三',12,'男');
  w.printInfo();//调用父类方法
  w.run();//调用子类方法
}
/*子类 覆写父类的方法*/
class Person {
    String name;
    num age;
    Person(this.name,this.age);
    void printInfo(){
      print("${this.name}---${this.age}");
    }
    work(){
      print("${this.name}在工作...");
    }
}
class Web extends Person{
    Web(string name, num age) : super(name, age)
    //覆写父类的方法
    @override       //可以写可以不写,建议在覆写父类方法的时候加上
    void printInfo(){
      print("姓名: ${this.name}---年龄: ${this.age}");
    }
    
    run(){
      print('run');
      super.work();//子类调用父类的方法
    }
}
main(){
  Web w=new Web('李四',20);
  w.printInfo();// 姓名: 李四---年龄: 20
}

21.Dart中的抽象类、多态和接口

/*Dart中抽象类: Dart抽象类主要用于定义标准, 子类可以继承抽象类, 也可以实现抽象类接口.
    1.抽象类通过abstract关键字来定义
    2.Dart中的抽象方法不能用abstract声明. Dart中没有方法体的方法我们称为抽象方法.
    3.如果子类继承抽象类必须得实现里面的抽象方法
    4.如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法.
    5.抽象类不能被实例化,只能继承它的子类才可以实例化
    
extends抽象类 和 implements的区别:
    1.如果要复用抽象类里面的方法, 并且要用抽象方法约束子类的话,我们就用extends继承抽象类
    2.如果只是把抽象类当做标准的话我们就用implements实现抽象类
*/

//案例: 定义一个Animal类要求它的子类必须包含eat方法
abstract class Animal{
  eat();//抽象方法
  printInfo(){
    print('我是一个抽象类里面的普通方法');
  }
}
class Dag extends Animal{
  @override
  eat(){//在继承抽象类的子类中必须实现父类的抽象方法
    // TODO: implement eat
    print('小狗在吃老鼠');
  }
}
class Cat extends Animal{
  @override
  eat(){//在继承抽象类的子类中必须实现父类的抽象方法
    // TODO: implement eat
    print('小猫在吃骨头');
  }
}
main(){
  Dog d = new Dog();
  d.eat();
}
/*Dart中的多态:
    允许将子类型的指针赋值给父类型的指针, 同一个函数调用会有不同的执行效果
    子类的实例赋值给父类的引用.
    多态就是父类定义一个方法不去实现, 让继承它的子类去实现, 每个子类有不同的表现.
*/
abstract class Animal{
  eat();//抽象方法
}
class Dag extends Animal{
  @override
  eat(){
    print('小狗在吃骨头');
  }
}
class Cat extends Animal{
  @override
  eat(){
    print('小猫在吃老鼠');
  }
}
main(){
  Dog d = new Dog();
  d.eat();
  
  Cat c=new cat();
  c.eat();
  
  // 多态
  Animal d = new Dog();
  d.eat();
  
  Animal c= new Cat();
  c.eat();
}
/*接口:
和Java一样, dart也有接口, 但是和Java还是有区别的.
    首先, dart的接口没有interface关键词定义接口, 而是普通类或抽象类都可以作为接口被实现. 同样适用implements关键字进行实现.
    但是dart的接口有点奇怪, 如果实现的类是普通类, 会将普通类和抽象类中的属性和方法全部需要覆写一遍.
    而因为抽象类可以定义抽象方法, 普通类不可以.所以一般如果要实现像Java接口那样的方式, 一般会使用抽象类.
    建议使用抽象类定义接口.!!!!
*/
// 定义一个DB库, 支持 mysql mssql mongodb. MySQL、MSSQL、MongoDB三个类里面都要有同样的方法.
abstract class Db{ //当做接口 接口:就是约定、规范
  String url;// 数据库的链接地址
  add(String data);
  save();
  delete();
}
class MySQL implements Db{
    @override
    String url;

    @override
    add(String data){
      print('这是MySQL的实例方法');
    }
    @override
    save(){
      return null;
    }
    @override
    delete(){
      return null;
    }
}
main(){
        MySQL mysql = new MySQL('https://www.baidu.com');
    mysql.add('666');
}
/*接口分离*/
/// 在Db.dart中
abstract class Db{ //当做接口 接口:就是约定、规范
  String url;// 数据库的链接地址
  add(String data);
  save();
  delete();
}
/// 在MySQL.dart中
import 'Db.dart';
class MySQL implements Db{
    @override
    String url;

    @override
    add(String data){
      print('这是MySQL的实例方法');
    }
    @override
    save(){
      return null;
    }
    @override
    delete(){
      return null;
    }
}

/// 在xxx.dart中使用:
import 'lib/MySQL.dart';
main(){
   MySQL mysql = new MySQL('https://www.baidu.com');
   mysql.add('666');
}

22.Dart中一个类实现多个接口以及Dart中的Mixins

/*Dart中一个类实现多个接口: 要实现每个接口的属性和方法*/
abstract class A{
  String name;
  printA();
}
abstract class B{
  printB();
}
class c implements A,B{//一个类同时实现A和B接口多个接口的写法
  @override
  String name;
  @override
  printA(){
    print('printA');
  }
  @override
  printB(){
    return null;
  }
}
/*mixins的中文意思是混入, 就是在类中混入其他功能.
在Dart中可以使用mixins实现类似多继承的功能
因为mixins使用的条件, 随着Dart版本一直在变, 这里讲的是Dart2.x中使用mixins的条件:
    1.作为mixins的类只能继承自Object, 不能继承其他类
    2.作为mixins的类不能有构造函数
    3.一个类可以mixins多个mixins类
    4.mixins绝不是继承, 也不是接口, 而是一个种全新的特性
*/
class Person{
  String name;
  num age;
  Person(this.name,this,age);//作为C的父类, 可以有构造函数
  printInfo(){
    print('这是一个Person类');
  }
}

class A{//作为mixins使用的类,此时A类不能继承自其他类,也不能有构造函数
  String info="this is A";
  void printA(){
    print("A");
  }
}
class B{//作为mixins使用的类,此时B不能继承自其他类,也不能有构造函数
  void printB(){
    print("B");
  }
}
//可以继承其他类
class C extends Person with A,B{//这样C就拥有了A和B类所有的方法和属性
  c(String name, num age) : super(name, age);
}
void main(){
  var c new C('张三',20);
  c.printInfo();
  c.printA();
  c.printB();
  print(c.info);
}
// 如果父类与mixins有重名方法,执行的优先级是:B>A>父类
/*mixins的实例类型是什么?
很简单, mixins的类型就是其超类的子类型.
*/
class A{
  String info="this is A";
  void printA(){
    print("A");
  }
}
class B{
  void printB(){
    print("B");
  }
}
class C with A,B{
  
}
void main(){
    var c new C();
    print(c is C);//true
    print(c is A);///true
    print(c is B);//true
}

23.Dart中的泛型、泛型方法、泛型类、泛型接口

/*
通俗理解: 泛型就是解决类、接口、方法的复用性,以及对不待定数据类型的支持(类型校验)
*/
// 不指定类型放弃了类型检查, 我们现在想实现的是传入什么,返回什么.
T getData(T value){//对返回参数和传入参数进行校验
  return value;
}
void main(){
  print(getData(21));
  getData(12);
  getData('你好');
}
// List就是一个泛型类,可以指定传入参数类型
List list = new List();
/*案例: 把下面的类转换成泛型类, 要求List里面可以增加int类型的数据, 也可以增加String类型的数据.*/
class PrintClass{//改成泛型类
  List list=new List{
    this.list.add(value);
  }
  void printInfo(){
    for(var i=0;i();//指定泛型类类型
  p.add(1);//报错
  p.add('1');
  p.PrintInfo();
}
/*Dart中的泛型接口:
    实现数据缓存的功能: 有文件缓存、内存缓存.内存缓存和文件缓存按照接口的约束实现.
    1.定义一个泛型接口, 约束实现它的子类必须有getByKey(key) 和 setByKey(key, value)
    2.要求setByKey的时候的value的类型和实例化子类的时候指定的类型一致.
*/
abstract class Cache {//泛型接口
  getByKey(String key);
  void setByKey(String key, T value);
}
class FileCache implements Cache {
  @override
  getByKey(String key){
    return null;
  }
  @override
  void setByKey(String key, T value){
    print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");
  }
}
class MemoryCache implements Cache {
  @override
  getByKey(String key){
    return null;
  }
  @override
  void setByKey(String key, T value){
    print("我是内存缓存 把key=${key} value=${value}的数据写入到了内存中");
  }
}
void main(){
  MemoryCache m=new MemoryCache();//要求接口传入的类型,会验证类型
  m.setByKey('index',{"name":"张三"});
}

24.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.dev/packages
        https://pub.flutter-io.cn/packages
        https://pub.dartlang.org/flutter/
        
        sp1.需要在自己项目根目录新建一个pubspec.yaml
        sp2.在pubspec.yaml文件,配置名称、描述、依赖等信息
        sp3.运行pub get获取包下载到本地
        sp4.项目中引入库import 'package:http/http.dart' as http;看文档使用
*/
/*async和await
    这两个关键字的使用只需要记住两点:
        只有async方法里才能使用await关键字调用方法;
        如果调用别的async方法必须使用await关键字.
        
    async是让方法变异步.
    await是等待异步方法执行完成.
*/
void main() async{
  var result = await testAsunc();
  pirnt(result);
}
//异步方法
testAsync() async{
  return 'Hello async';
}
/*当引入两个库中有相同名称标识符的时候,如果是Java通常我们通过协商完整的包名路径来指定使用
    import 'package:lib1/lib1.dart';// Users Element from lib1
    import 'package:lib2/lib2.dart'; as lib2;// Uses Element from lib2
    
    Element element1 = new Element();
    lib2.Element element2 = new lib2.Element();
*/
/*导入pub包管理系统中的库
1、从下面网址找到要用的库
        https://pub.dev/packages
        https://pub.flutter-io.cn/packages
        https://pub.dartlang.org/flutter/
2、创建一个pubspec.yaml文件, 内容如下
        name: xxx
        description: A new flutter module project.
        dependencies:
                http: ^0.12.0+2
                date_format: ^1.0.6
3、配置dependencies
4、运行put get 获取远程库
5、看文档引入库使用
*/
/*如果只需要导入库的一部分, 有两种模式:
        模式一: 只导入需要的部分, 使用show关键字,如下例子所示:
        import 'package:lib1/lib1.dart' show foo;
        模式二: 隐藏不需要的部分, 使用hide关键字,如下例子所示:
        import 'package:lib2/lib2.dart' hide foo;
*/
/*延时加载
        也称为懒加载, 可以在需要的时候再进行加载.
        懒加载最大的好处是可以减少APP的启动时间.
        
        懒加载使用deferred as关键字来指定, 如下例子所示:
        import 'package:deferred/hello.dart' deferred as hello;
        
        当需要使用的时候, 需要使用loadLibrary()方法来加载:
        
        greet() async {
            await hello.loadLibrary();
            hello.printGreeting();
        }
*/

你可能感兴趣的:(Dart知识点汇总)