Dart粗浅小记

曹自怡
2023-12-01

Dart环境搭建

​ 要在我们本地开发Dart程序的话首先需要安装Dart Sdk

​ 官方文档:https://dart.dev/get-dart

windows(推荐)

​ http://www.gekorm.com/dart-windows/

mac

​ 如果mac电脑没有安装brew这个工具首先第一步需要安装它: https://brew.sh/

brew tap dart-lang/dart

brew install dart

Dart 开发工具

Dart的开发工具有很多: IntelliJ IDEA 、 WebStorm、 Atom、Vscode等

在Vscode中配置Dart:

1、找到vscode插件安装dart

2、找到vscode插件安装code runner   Code Runner  可以运行我们的文件

Dart变量 常量 命名规则

## 入口方法
// void 表示main方法没有返回值
void main(){
 print('你好dart');
}

变量

​ dart是一个强大的脚本类语言,可以不预先定义变量类型 ,自动会类型推导

​ dart中定义变量可以通过var关键字可以通过类型来申明变量

var str='this is var';
String str='this is var';  // 字符串
int str=123;  // 数字
// 注意: var 后就不要写类型 ,  写了类型 不要var  两者都写  var  a int  = 5;  报错
## 	常量 final 和 const 修饰符

​ const:值不变 一开始就得赋值

  final: 可以开始不赋值 只能赋一次 ; 而final不仅有const的编译时常量的特性,最重要的它是运行时常量,并且final是惰性初始化,即在运行时第一次使用前才初始化

​ 永远不改量的量,请使用final或const修饰它,而不是使用var或其他变量类型。

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
## 命名规则

​ 1. 变量名称必须由数字、字母、下划线和美元符($)组成。

​ 2. 标识符开头不能是数字

​ 3. 标识符不能是保留字和关键字。

​ 4. 变量的名字是区分大小写的如: age和Age是不同的变量。在实际的运用中,也建议,不要用一个单词大小写区分两个变量。

​ 5. 标识符(变量名称)一定要见名思意 :变量名称建议用名词,方法名称建议用动词

Dart 数据类型

字符串

字符串定义:

var str1='this is str1';
String str1='this is str1';
String str1='''this is str1
   this is str1
   this is str1
 ''';
String str1="""
  this is str1
  this is str1
  this is str1
""";

字符串拼接

  String str1='你好';
  String str2='Dart';
  print("$str1 $str2");  // $ 符号拼接
  print(str1 + str2);  // + 号拼接

数值类型

//1、int   必须是整型
int a=123;
//2、double  既可以是整型 也可是浮点型
double b=23.5;
double b=24;

布尔类型

bool flag1=true;
bool flag2=false;

数组 / 集合

// 1、第一种定义List的方式
var l1 = ["张三",20,true];
print(l1);  // [张三, 20, true]
print(l1.length);  // 3
print(l1[0]); // 张三
print(l1[1]); // 0

// 2、第二种定义List的方式 指定类型
var l2 = <String>["张三","李四"];
print(l2);
var l3 = <int>[12, 30];
print(l3);

// 3、第三种定义List的方式  
// 增加数据: 通过[]创建的集合它的容量可以变化
var l4 = [];
print(l4);
print(l4.length);
l4.add("张三");
l4.add("李四");
l4.add(20);
print(l4);
print(l4.length);

// 4、第四种定义List的方式
var l6=new List();  // 在新版本的dart里面没法使用这个方法了
var l6=List.filled(2, "");  // 创建一个固定长度的集合
print(l6);
print(l6[0]);
l6[0]="张三";   // 修改集合的内容
l6[1]="李四";
print(l6);  // [张三, 李四]
l6.add("王五");  // 报错:超出长度
//通过List.filled创建的集合长度是固定
var l6=List.filled(2, "");
print(l6.length);
l6.length=0;  //修改集合的长度   报错

var l7=<String>["张三","李四"];
print(l7.length);  //2
l7.length=0;  // 可以改变的
print(l7);  // []

var l8=List<String>.filled(2, "");
l8[0]="string";
print(l8);

字典(map)

//第一种定义 Maps的方式
var person={
    "name":"张三",
    "age":20,
    "work":["程序员","送外卖"]
};
print(person);
print(person["name"]);  // 张三
print(person["age"]);  // 20
print(person["work"]);  // ["程序员","送外卖"]

//第二种定义 Maps的方式
var p=new Map();
p["name"]="李四";
p["age"]=22;
p["work"]=["程序员","送外卖"];
print(p);
print(p["age"]); // 22

类型判断

// is 关键词判断类型
var str=123;

if(str is String){
	print('是string类型');
}else if(str is int){
	print('int');
}else{
     print('其他类型');
}

运算符 条件判断 类型转换

算数运算符

int a=13;
int b=5;

print(a + b);   // 加
print(a - b);   // 减
print(a * b);   // 乘
print(a / b);   // 除
print(a % b);   // 取余
print(a ~/ b);  // 取整

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

关系运算符

int a=5;
int b=3;

print(a == b);   // 判断是否相等
print(a != b);   // 判断是否不等
print(a > b);   // 判断是否大于
print(a < b);   // 判断是否小于
print(a >= b);   // 判断是否大于等于
print(a <= b);   // 判断是否小于等于

逻辑运算符


/* ! 取反 */ 
bool flag=false;
print(!flag);   // 取反

/* &&并且:全部为true的话值为true 否则值为false */ 
bool a=true;
bool b=true;
print(a && b);

/* ||或者:全为false的话值为false 否则值为true */ 
bool a=false;
bool b=false;
print(a || b);

赋值运算符

//  1、基础赋值运算符   =   ??=      
int a = 10;
int b = 3;
print(a);
int c = a+b;   //从右向左

// b??=23;  表示如果b为空的话把 23赋值给b
int b = 6;
b ??= 23;
print(b);  // 23

int b;
b ??= 23;
print(b);  // 23

// 2、  复合赋值运算符   +=  -=  *=   /=   %=  ~/=
var a = 13;
a += 10;   //表示a=a+10
print(a);

var a = 4;
a *= 3;  // a= a*3;
print(a);
// 其余符号类推

条件表达式

// 1、if  else   switch case
bool flag=true;
if(flag){
  print('true');
 }else{
  print('false');
}
// if else 方式
var score = 41;
if (score > 90) {
  print('优秀');
} else if (score > 70) {
  print('良好');
} else if (score >= 60) {
  print('及格');
} else {
  print('不及格');
}
// switch case 方式
var sex = "女";
switch (sex) {
  case "男":
  	print('性别是男');
  	break;
  case "女":
  	print('性别是女');
  	break;
  default:
  	print('传入参数错误');
  	break;
}

// 2、三目运算符
bool flag=false;
String c = flag ? '我是true' : '我是false';
print(c);

// 3、??运算符
var a;
var b = a ?? 10;
print(b);  // 10
var a=22;
var b= a ?? 10;
print(b);  // 22

类型转换

​ Number与String类型之间的转换

// 1. Number与String类型之间的转换
// String类型转成Number类型
// int.parse()
String str = '123';
var myNum = int.parse(str);
print(myNum is int);  // true

// double.parse()
String str = '123.1';
var myNum = double.parse(str);
print(myNum is double);  // true

String price = '12';
var myNum = double.parse(price);
print(myNum);  // 12.0
print(myNum is double);  // true

String price = '';
var myNum = double.parse(price);
print(myNum);  // 
print(myNum is double);  // 报错

// 运用 try  ... catch 保证程序正常运行
String price = '';
try {
  var myNum = double.parse(price);
  print(myNum);
} catch (err) {
  print(0);
}

// Number类型转换成String类型 toString()
var myNum = 12;
var str = myNum.toString();
print(str is String);  // true

其他类型转换成Booleans类型

  // isEmpty:判断字符串是否为空
  var str = '';
  if (str.isEmpty) {
    print('str空');
  } else {
    print('str不为空');
  }

  // 判断是否向相等
  var myNum = 123;
  if(myNum == 0){
     print('0');
  }else{
    print('非0');
  }

  // isNan: 判断是否为 NaN
  var myNum = 0 / 0;
  print(myNum);
  if (myNum.isNaN) {
    print('NaN');
  }

循环语句

for 循环

for (int i = 1; i <= 100; i++) {   
   print(i);
}
//第一步,声明变量int i = 1;
//第二步,判断i <=100
//第三步,print(i);
//第四步,i++
//第五步 从第二步再来,直到判断为false

while 循环

// while 循环
// while(表达式/循环条件) {语句/循环体}	
  int i = 1;
  var sum = 0;
  while (i <= 100) {
    sum += i;
    i++;
  }
  print(sum);  // 5050

// do while 循环
// do {语句/循环体} while(表达式/循环条件);
  int i = 1;
  var sum = 0;
  do {
    sum += i;
    i++;
  } while (i <= 100);
  print(sum);  // 5050

// while 和 do while的区别:
// 第一次循环条件不成立的情况下 仍会执行一次 do 里面的代码

break 和 continue

/*
break语句功能:
  1、在switch语句中使流程跳出switch结构。
  2、在循环语句中使流程跳出当前循环,遇到break 循环终止,后面代码也不会执行
  3、如果在循环中已经执行了break语句,就不会执行循环体中位于break后的语句。
  4、在多层循环中,一个break语句只能向外跳出一层
  5、break可以用在switch case中 也可以用在 for 循环和 while循环中

continue语句的功能:
  1、只能在循环语句中使用,使本次循环结束,即跳过循环体重下面尚未执行的语句,接着进行下次的是否执行循环的判断。
  2、continue可以用在for循环以及 while循环中,但是不建议用在while循环中,不小心容易死循环
*/

常用方法

List 常用方法

    常用属性:
        length          长度
        reversed        翻转
        isEmpty         是否为空
        isNotEmpty      是否不为空
    常用方法:  
        add         增加
        addAll      拼接数组
        indexOf     查找  传入具体值
        remove      删除  传入具体值
        removeAt    删除  传入索引值
        fillRange   修改   
        insert(index,value);            指定位置插入    
        insertAll(index,list)           指定位置插入List
        toList()    其他类型转换成List  
        join()      List转换成字符串
        split()     字符串转化成List
        forEach   
        map
        where
        any
        every

Map 常用方法

    常用属性:
        keys            获取所有的key值
        values          获取所有的value值
        isEmpty         是否为空
        isNotEmpty      是否不为空
    常用方法:
        remove(key)     删除指定key的数据
        addAll({...})   合并映射  给映射内增加属性
        containsValue   查看映射内的值是否有传入的参数  返回true/false
        forEach   
        map
        where
        any
        every

方法

内置方法 \ 函数

print()

自定义方法

/* 
基本格式:
	返回类型  方法名称(参数1,参数2,...){
        方法体
        return 返回值;
      }
*/

void printInfo(){
  print('我是一个自定义方法');
}

方法传参

必传参数

// 定义一个方法 求1到这个数的所有数的和
  String printUserInfo(String username, int age) {
    //行参
    return "姓名:$username---年龄:$age";
  }

  print(printUserInfo('张三', 20)); //实参

可选参数

// 定义一个带可选参数的方法 ,最新的dart定义可选参数需要指定类型默认值
  String printUserInfo(String username, [int age = 0]) {  //行参
    if (age != 0) {
      return "姓名:$username---年龄:$age";
    }
    return "姓名:$username---年龄保密";
  }

  print(printUserInfo('张三', 21)); // 姓名:张三---年龄:21
  print(printUserInfo('张三'));  // 姓名:张三---年龄保密

默认参数

  String printUserInfo(String username, [String sex = '男', int age = 0]) {
    if (age != 0) {
      return "姓名:$username---性别:$sex--年龄:$age";
    }
    return "姓名:$username---性别:$sex--年龄保密";
  }

  print(printUserInfo('张三'));  // 姓名:张三---性别:男--年龄保密
  print(printUserInfo('小李', '女'));  // 姓名:小李---性别:女--年龄保密
  print(printUserInfo('小李', '女', 30));  // 姓名:小李---性别:女--年龄:30

命名参数

  String printUserInfo(String username, {int age = 0, String sex = '男'}) {
    if (age != 0) {
      return "姓名:$username---性别:$sex--年龄:$age";
    }
    return "姓名:$username---性别:$sex--年龄保密";
  }

  print(printUserInfo('张三', age: 20, sex: '未知'));  // 姓名:张三---性别:未知--年龄:20

匿名方法

  var printNum = (int n) {
    print(n + 2);
  };
  printNum(12);

自执行方法

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

递归

  var sum = 1;
  fn(int n) {
    sum *= n;
    if (n == 1) {
      return;
    }
    fn(n - 1);
  }
  fn(100);
  print(sum);  // 5050

闭包

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

  /*  想实现的功能:
        1.常驻内存        
        2.不污染全局   
        产生了闭包,闭包可以解决这个问题.....  

        闭包: 函数嵌套函数, 内部函数会调用外部函数的变量或参数, 变量或参数不会被系统回收(不会释放内存)
  
	    闭包的写法: 函数嵌套函数,并return 里面的函数,这样就形成了闭包。

    */  
*/

  fn() {
    var a = 123; /*不会污染全局   常驻内存*/
    return () {
      a++;
      print(a);
    };
  }

  var b = fn();
  b();  // 124
  b();  // 125
  b();  // 126

Dart 面向对象

面向对象编程(OOP)的三个基本特征是:封装、继承、多态

封装:封装是对象和类概念的主要特性。封装,把客观事物封装成抽象的类,并且把自己的部分属性和方法提供给其他对象调用, 而一部分属性和方法则隐藏。

继承:面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

多态:允许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行效果 。

Dart所有的东西都是对象,所有的对象都继承自Object类。

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

一个类通常由属性和方法组成。

创建与使用类

class Person {
  String name = "张三";
  int age = 23;
  void getInfo() {
    // print("$name----$age");
    print("${this.name}----${this.age}");
  }
  void setInfo(int age) {
    this.age = age;
  }
}

void main() {
  //实例化
  Person p1 = new Person();
  print(p1.name);  // 张三
  p1.setInfo(28);
  p1.getInfo();  // 张三----28
}

默认构造函数

class Person {
  String name = '张三';
  int age = 20;
  //默认构造函数
  Person() {
    print('这是构造函数里面的内容  这个方法在实例化的时候触发');
  }
  void printInfo() {
    print("${this.name}----${this.age}");
  }
}
// 最新版本的dart中需要初始化不可为null的实例字段,如果不初始化的话需要在属性前面加上late
class Person {
  late String name;
  late int age;
  //默认构造函数的简写
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}----${this.age}");
  }
}

void main() {
  Person p1 = new Person('张三', 20);
  p1.printInfo();  // 张三----20

  Person p2 = new Person('李四', 25);
  p2.printInfo();  // 李四----25
}

命名构造函数

class Person {
  late String name;
  late int age;
  // 默认构造函数的简写
  Person(this.name, this.age);
  // 命名构造函数
  Person.now() {
    print('我是命名构造函数');
  }
  // 可写多个
  Person.setInfo(String name, int age) {
    this.name = name;
    this.age = age;
  }

  void printInfo() {
    print("${this.name}----${this.age}");
  }
}

void main() {
  Person p1=new Person('张三', 20);   // 默认实例化类的时候调用的是 默认构造函数

  Person p1=new Person.now();   // 命名构造函数

  Person p1 = new Person.setInfo('李四', 30);
  p1.printInfo();  // 李四----30
}

私有方法和私有属性

class Animal{
  late String _name;   // _定义私有属性
  late 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();  // 类里面方法的相互调用
  }
}

getter 和 setter 修饰符

class Rect{
  late num height;
  late num width;   
  Rect(this.height,this.width);
  // getter
  get area{
    return this.height*this.width;
  }
  // setter
  set areaHeight(value){
    this.height=value;
  }
}

void main(){
  Rect r = new Rect(10,4);
  r.areaHeight = 6;  // 调用setter

  print(r.area);  // 调用getter
}

静态属性与方法

/*
Dart中的静态成员:

  1、使用static 关键字来定义静态的变量和函数

  2、静态方法不能访问非静态成员,非静态方法可以访问静态成员

*/

class Person {
  static String name = '张三';
  int age=20;  
  static void show() {
    print(name);
  }
  void printInfo(){  /*非静态方法可以访问静态成员以及非静态成员*/
      print(name);  //访问静态属性
      print(this.age);  //访问非静态属性
      show();   //调用静态方法
  }
  static void printUserInfo(){//静态方法
        print(name);   //静态属性
        show();        //静态方法
  }
}

对象操作符

as 类型转换

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

  var p1;
  p1 = new Person('张三1', 20);
  (p1 as Person).printInfo();  // 感觉很鸡肋

is 类型判断

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}  

Person p = new Person('张三', 20);
  if (p is Person) {
    p.name = "李四";
  }
  p.printInfo();  // 李四---20
  print(p is Object);  // true

… 级联操作 (连缀)

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}    

Person p1 = new Person('张三1', 20);
  p1.printInfo();  // 张三1---20
  p1
    ..name = "李四"
    ..age = 30
    ..printInfo();  // 李四---30

继承

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(){   
  Web w=new Web();
  print(w.name);  // 张三
  w.printInfo();  // 张三---20
 
}

实例化子类给父类传参

class Person {
  String name;
  num age;
  Person(this.name, this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}

class Web extends Person {
  late String sex;
  Web(String name, num age, String sex) : super(name, age) {  // 通过调用 super 方法
    this.sex = sex;
  }
  run() {
    print("${this.name}---${this.age}--${this.sex}");
  }
}

main() {
  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 {
  late String sex;
  Web(String name, num age, String sex) : super.xxx(name, age) {  // 通过调用 super.XXX 方法
    this.sex = sex;
  }
  run() {
    print("${this.name}---${this.age}--${this.sex}");
  }
}

main() {
  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);

  run(){
    print('run');
  }
  // 覆写父类的方法
  @override       // 可以写也可以不写  建议在覆写父类方法的时候加上 @override 
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}"); 
  }
  @override
  work(){
    print("${this.name}的工作是写代码");
  }

}

子类调用父类的方法

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);

  run(){
    print('run');
    super.work();  // 子类调用父类的方法 通过 super 
  }
  //覆写父类的方法
  @override       //可以写也可以不写  建议在覆写父类方法的时候加上 @override 
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}"); 
  }
}

main(){ 
  Web w=new Web('李四',20);
  w.run();
 
}

抽象类

Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。

1、抽象类通过abstract 关键字来定义

2、Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。

3、如果子类继承抽象类必须得实现里面的抽象方法

4、如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。

5、抽象类不能被实例化,只有继承它的子类可以

// 定义一个抽象类
abstract class Animal {
  eat(); //抽象方法
  run(); //抽象方法
  printInfo() {
    print('我是一个抽象类里面的普通方法');
  }
}

// 继承抽象类
class Dog extends Animal {
  @override
  eat() {
    print('小狗在吃骨头');
  }

  @override
  run() {
    // TODO: implement run
    print('小狗在跑');
  }
}

class Cat extends Animal {
  @override
  eat() {
    // TODO: implement eat
    print('小猫在吃老鼠');
  }

  @override
  run() {
    // TODO: implement run
    print('小猫在跑');
  }
}

main() {
  Dog d = new Dog();
  d.eat();
  d.printInfo();

  Cat c = new Cat();
  c.eat();
  c.printInfo();

  // Animal a=new Animal();   // 抽象类没法直接被实例化
}

extends抽象类 和 implements的区别:

1、如果要复用抽象类里面的方法,并且要用抽象方法约束子类的话我们就用extends继承抽象类

2、如果只是把抽象类当做标准的话我们就用implements实现抽象类


接口

1、dart 的接口没有 interface 关键字定义接口,而是普通类或抽象类都可以作为接口被实现。

2、使用 implements 关键字进行实现。

3、但是 dart 的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。

4、因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类。

5、建议使用抽象类定义接口。

abstract class Db {
  //当做接口   接口:就是约定 、规范
  late String uri; // 数据库的链接地址
  add(String data);
  save();
  delete();
}

class MsSql implements Db {  // 使用 implements 关键字继承接口
  @override
  late String uri;
  @override
  add(String data) {
    print('这是mssql的add方法' + data);
  }

  @override
  delete() {
    // TODO: implement delete
    return null;
  }

  @override
  save() {
    // TODO: implement save
    return null;
  }
}

main() {
  Mysql mysql = new Mysql('xxxxxx');
  mysql.add('1243214');
}

一个类可以实现多个接口

// 定义接口 A
abstract class A {
  late String name;
  printA();
}

// 定义接口 B
abstract class B {
  printB();
}

// 同时实现 A B 两个接口
class C implements A, B {
  @override
  late String name;
  @override
  printA() {
    print('printA');
  }

  @override
  printB() {
    // TODO: implement printB
    return null;
  }
}

void main() {
  C c = new C();
  c.printA();
}

mixins

mixins的中文意思是混入,就是在类中混入其他功能。

在Dart中可以使用mixins实现类似多继承的功能

因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件:

1、作为mixins的类只能继承自Object,不能继承其他类

2、作为mixins的类不能有构造函数

3、一个类可以mixins多个mixins类

4、mixins绝不是继承,也不是接口,而是一种全新的特性

// 定义 mixins A
class A {
  String info = "this is A";
  void printA() {
    print("A");
  }
}

// 定义 mixins B
class B {
  void printB() {
    print("B");
  }
}

// 定义类 C mixins A 和 B
class C with A, B {}

void main() {
  var c = new C();
  c.printA();
  c.printB();
  print(c.info);
}
// 定义一个父类
class Person {
  String name;
  num age;
  Person(this.name, this.age);
  printInfo() {
    print('${this.name}----${this.age}');
  }

  void run() {
    print("Person Run");
  }
}

// 定义一个 mixins A
class A {
  String info = "this is A";
  void printA() {
    print("A");
  }

  void run() {
    print("A Run");
  }
}

// 定义一个 mixins A
class B {
  void printB() {
    print("B");
  }

  void run() {
    print("B Run");
  }
}

// 定义一个类 C 继承自 Person , 然后混入类 B 和 A
class C extends Person with B, A {
  C(String name, num age) : super(name, age);
}

void main() {
  var c = new C('张三', 20);
  c.printInfo();  // 张三----20
  c.printB();  // B
  print(c.info);  // this is A

  c.run();  // A Run
}

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

  var a=new A();
  print(a is Object);  // true (所有类均是 Object 的子类)
}

泛型

泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)

// 通过 T 指定泛型
// 传入number 类型必须返回number类型  传入 string类型必须返回string类型
getData<T>(T value) {
  return value;
}

void main() {
  print(getData(21));  // 21
  print(getData('xxx'));  // XXX
  print(getData<String>('你好'));  // 你好
  print(getData<int>(12));  // 12
}

泛型类

class MyList<T> {
  List list = <T>[];
  void add(T value) {
    this.list.add(value);
  }

  List getList() {
    return list;
  }
}

main() {

  MyList l3 = new MyList<int>();
  l3.add(11);  // 报错
  l3.add("aaaa");
  print(l3.getList());
}

泛型接口

abstract class Cache<T> {
  getByKey(String key);
  void setByKey(String key, T value);
}

class FlieCache<T> implements Cache<T> {
  @override
  getByKey(String key) {
    return null;
  }

  @override
  void setByKey(String key, T value) {
    print("我是文件缓存 把key=${key}  value=${value}的数据写入到了文件中");
  }
}

class MemoryCache<T> implements Cache<T> {
  @override
  getByKey(String key) {
    return null;
  }

  @override
  void setByKey(String key, T value) {
    print("我是内存缓存 把key=${key}  value=${value} -写入到了内存中");
  }
}

void main() {
  MemoryCache m = new MemoryCache<Map>();
  m.setByKey('index', {"name": "张三", "age": 20});
}

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/

​ 1、需要在自己想项目根目录新建一个pubspec.yaml

​ 2、在pubspec.yaml文件 然后配置名称 、描述、依赖等信息

​ 3、然后运行 pub get 获取包下载到本地

​ 4、项目中引入库 import ‘package:http/http.dart’ as http; 看文档使用

// 系统内置库实现请求数据

import 'dart:io';
import 'dart:convert';

void main() async{
  var result = await getDataFromZhihuAPI();
  print(result);
}

//api接口: http://news-at.zhihu.com/api/3/stories/latest
getDataFromZhihuAPI() async{
  //1、创建HttpClient对象
  var httpClient = new HttpClient();  
  //2、创建Uri对象
  var uri = new Uri.http('news-at.zhihu.com','/api/3/stories/latest');
  //3、发起请求,等待请求
  var request = await httpClient.getUrl(uri);
  //4、关闭请求,等待响应
  var response = await request.close();
  //5、解码响应的内容
  return await response.transform(utf8.decoder).join();
}

async 和 await

async和await

1、只有async方法才能使用await关键字调用方法

2、如果调用别的async方法必须使用await关键字

async是让方法变成异步。

await是等待异步方法执行完成。

void main() async{
  var result = await testAsync();
  print(result);

}

// 异步方法
testAsync() async{
  return 'Hello async';
}

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、运行pub get 获取远程库

5、看文档引入库使用

库的重命名

当引入两个库中有相同名称标识符的时候,如果是java通常我们通过写上完整的包名路径来指定使用的具体标识符,甚至不用import都可以,但是Dart里面是必须import的。当冲突的时候,可以使用as关键字来指定库的前缀。如下例子所示:

import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;

main(List<String> args) {
  Person p1=new Person('张三', 20);
  p1.printInfo();

  lib.Person p2=new lib.Person('李四', 20);
  p2.printInfo();
}

部分导入

如果只需要导入库的一部分,有两种模式:

模式一:只导入需要的部分,使用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();
  }
 类似资料: