dart 介绍

Dart 是由谷歌开发的计算机编程语言,它可以被用于 web、服务器、移动应用 和物联网等领域的开发。

Dart 诞生于 2011 年,号称要取代 JavaScript。但是过去的几年中一直不温不火。直到 Flutter 的出现现在被人们重新重视。

dart 基础

Dart 变量

  • dart 是一个强大的脚本类语言,可以不预先定义变量类型 ,自动会类型推倒
  • dart 中定义变量可以通过 var 关键字可以通过类型来申明变量

  var str='this is var';
  String str='this is var';
  int str=123;

// 注意: var 后就不要写类型 ,  写了类型 不要var   两者都写   var  a int  = 5;  报错

Dart 常量

  • finalconst修饰符。
  • 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

Dart 的命名规则

  • 变量名称必须由数字、字母、下划线和美元符($)组成。
  • 注意:标识符开头不能是数字
  • 标识符不能是保留字和关键字。
  • 变量的名字是区分大小写的如: age 和 Age 是不同的变量。在实际的运用中,也建议,不要用一个单词大小写区分两个变量。
  • 标识符(变量名称)一定要见名思意 :变量名称建议用名词,方法名称建议用动词 。
void main(){

    var str1='2134214';

    //var 2str='xxx';   //错误
    // var if='124214';  //错误


    //变量的名字是区分大小写的
    var age=20;
    var Age=30;

    print(age);
    print(Age);



    var price=12;
    var name=124;

}

入口方法

  main(){
    print('你好dart');
  }

数据类型

  • 常用数据类型:

    • Number(数值),int double
    • String(字符串) , String
    • Boolean(布尔), bool
    • List(数组): 在 Dart 中,数组是列表对象,所以大多数人只是称它们为列表。
    • Map(字典): 通常来说,Map 是一个键值对相关的对象。键和值可以是任何类型的对象。每个 键 只出现一次, 而一个值则可以出现多次。
  • 项目中用不到的数据类型(用不到):

    • Runes : RuneUTF-32 编码的字符串。它可以通过文字转换成符号表情或者代表特定的文字。

    • Symbols : Symbol 对象表示在 Dart 程序中声明的运算符或标识符。您可能永远不需要使用符号,但它们对于按名称引用标识符的 API 非常有用,因为缩小会更改标识符名称而不会更改标识符符号。要获取标识符的符号,请使用符号文字,它只是#后跟标识符。

String

void main(){

  //1、字符串定义的几种方式
  // var str1='this is str1';
  // var str2="this is str2";

  // print(str1);
  // print(str2);

  // String str1='this is str1';
  // String str2="this is str2";
  // print(str1);
  // print(str2);

  // String str1='''this is str1
  // this is str1
  // this is str1
  // ''';
  //  print(str1);

  //   String str1="""
  //   this is str1
  //   this is str1
  //   this is str1
  //   """;
  //  print(str1);

  //2、字符串的拼接

  String str1='你好';
  String str2='Dart';
  // print("$str1 $str2");


  print(str1 + str2);
  print(str1 +" "+ str2);

}

Number

void main(){

  //1、int   必须是整型
    int a=123;
    a=45;
    print(a);

  //2、double  既可以是整型 也可是浮点型
    double b=23.5;
    b=24;
    print(b);

  //3、运算符
  // + - * / %

    var c=a+b;
    print(c);


}
  • Boolean
void main(){

  //1、bool
  // bool flag1=true;
  // print(flag1);

  // bool flag2=false;
  // print(flag2);

  //2、条件判断语句
  // var flag=true;
  // if(flag){
  //   print('真');
  // }else{
  //   print('假');
  // }

  // var a=123;
  // var b='123';
  // if(a==b){
  //   print('a=b');
  // }else{
  //    print('a!=b');
  // }

  var a=123;
  var b=123;
  if(a==b){
    print('a=b');
  }else{
      print('a!=b');
  }

}

List

void main() {
  //1、第一种定义List的方式

  // var l1=["张三",20,true];
  // print(l1);  //[张三, 20, true]
  // print(l1.length);  //3
  // print(l1[0]); //张三
  // print(l1[1]); //20

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

  // var l5 = ["张三", 20, true];
  // l5.add("李四");
  // l5.add("zhaosi");
  // print(l5);

  //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创建的集合长度是固定  没法增加数据

  //通过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";
  // l8[0]=222;
  print(l8);

}

Map

void main(){
  //第一种定义 Maps的方式

  // var person={
  //   "name":"张三",
  //   "age":20,
  //   "work":["程序员","送外卖"]
  // };

  // print(person);
  // print(person["name"]);
  // print(person["age"]);
  // print(person["work"]);

  //第二种定义 Maps的方式

  var p=new Map();
  p["name"]="李四";
  p["age"]=22;
  p["work"]=["程序员","送外卖"];
  print(p);
  print(p["age"]);

}

判断数据类型

void main(){
  // var str='1234';
  // if(str is String){
  //   print('是string类型');
  // }else if(str is int){
  //    print('int');
  // }else{
  //    print('其他类型');
  // }

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

}

运算,类型转换

算数符,条件判断语句

/*

1、Dart运算符:
    算术运算符
      +    -    *    /     ~/ (取整)     %(取余)

    关系运算符
      ==    !=   >    <    >=    <=

    逻辑运算符
        !  &&   ||

    赋值运算符
     基础赋值运算符   =   ??=
     复合赋值运算符   +=  -=  *=   /=   %=  ~/=

    条件表达式
        if  else   switch case
        三目运算符
        ??运算符:
2、类型转换

    1、Number与String类型之间的转换
    2、其他类型转换成Booleans类型
*/

算术运算

void main(){

  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 c=a*b;
  print('--------');
  print(c);

}

关系运算

void main(){
  //  ==    !=   >    <    >=    <=
  int a=5;
  int b=3;

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

  if(a>b){
    print('a大于b');
  }else{
    print('a小于b');
  }
}

逻辑运算

void main(){
  /* ! 取反 */

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

//如果一个人的年龄是20 并且 sex是女的话我们打印这个人

  // int age=20;
  // String sex="女";
  // if(age==20 && sex=="女"){
  //   print("$age --- $sex");
  // }else{
  //   print("不打印");
  // }

//如果一个人的年龄是20 或者 sex是女的话我们打印这个人

  int age=23;
  String sex="女";
  if(age==20 || sex=="女"){
    print("$age --- $sex");
  }else{
    print("不打印");
  }

}

赋值运算符

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

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

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

    // var a=13;
    // a+=10;   //表示a=a+10
    // print(a);

   var a=4;
   a*=3;  //a=a*3;
   print(a);
}

条件运算

void main(){
  //1、if  else   switch case
    // bool flag=true;
    // if(flag){
    //   print('true');
    // }else{
    //   print('false');
    // }

  //判断一个人的成绩 如果大于60 显示及格   如果大于 70显示良好  如果大于90显示优秀

  // var score=41;
  // if(score>90){
  //   print('优秀');
  // }else if(score>70){
  //    print('良好');
  // }else if(score>=60){
  //   print('及格');
  // }else{
  //   print('不及格');
  // }

  // var sex="女";
  // switch(sex){
  //   case "男":
  //     print('性别是男');
  //     break;
  //   case "女":
  //     print('性别是女');
  //     print('性别是女');
  //     break;
  //   default:
  //     print('传入参数错误');
  //     break;
  // }

  //2、三目运算符

  // var falg=true;
  // var c;
  // if(falg){
  //     c='我是true';
  // }else{
  //   c="我是false";
  // }
  // print(c);

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

}

类型转换


void main(){


    //1、Number与String类型之间的转换

      // Number类型转换成String类型 toString()
      // String类型转成Number类型  int.parse()

      // String str='123';
      // var myNum=int.parse(str);
      // print(myNum is int);

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

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

      //报错
      // 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);
    //   }

    // var myNum=12;
    // var str=myNum.toString();
    // print(str is String);
 // 2、其他类型转换成Booleans类型

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

        // var myNum=123;
        // if(myNum==0){
        //    print('0');
        // }else{
        //   print('非0');
        // }


        // var myNum;
        // if(myNum==0){
        //    print('0');
        // }else{
        //   print('非0');
        // }

        // var myNum;
        // if(myNum==null){
        //    print('空');
        // }else{
        //   print('非空');
        // }

        var myNum=0/0;
        // print(myNum);
        if(myNum.isNaN){
          print('NaN');
        }

}

dart 循环

  • for 循环
  • while 循环
  • do while 循环
  • breakcontinue

集合类型 List Set Map

List

/*
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

*/

void main(){

  // List myList=['香蕉','苹果','西瓜'];
  // print(myList[1]);

  // var list=new List();  //新版本没法使用
  // list.add('111');
  // list.add('222');
  // print(list);

//List里面的属性:
    // List myList=['香蕉','苹果','西瓜'];
    // print(myList.length);
    // print(myList.isEmpty);
    // print(myList.isNotEmpty);
    // print(myList.reversed);  //对列表倒序排序
    // var newMyList=myList.reversed.toList();
    // print(newMyList);

//List里面的方法:

    // List myList=['香蕉','苹果','西瓜'];
    //myList.add('桃子');   //增加数据  增加一个
    // myList.addAll(['桃子','葡萄']);  //拼接数组
    // print(myList);
    //print(myList.indexOf('苹x果'));    //indexOf查找数据 查找不到返回-1  查找到返回索引值


    // myList.remove('西瓜');
    // myList.removeAt(1);
    // print(myList);

    // List myList=['香蕉','苹果','西瓜'];
    // myList.fillRange(1, 2,'aaa');  //修改
    // myList.fillRange(1, 3,'aaa');

    // myList.insert(1,'aaa');      //插入  一个
    // myList.insertAll(1, ['aaa','bbb']);  //插入 多个
    // print(myList);


    // List myList=['香蕉','苹果','西瓜'];
    // var str=myList.join('-');   //list转换成字符串
    // print(str);
    // print(str is String);  //true


    var str='香蕉-苹果-西瓜';
    var list=str.split('-');
    print(list);
    print(list is List);

}

Set

  • 用它最主要的功能就是去除数组重复内容。
void main(){

  // var s=new Set();
  // s.add('香蕉');
  // s.add('苹果');
  // s.add('苹果');
  // print(s);   //{香蕉, 苹果}
  // print(s.toList());

  List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
  var s=new Set();
  s.addAll(myList);
  print(s);
  print(s.toList());

}

Map

/*
  映射(Maps)是无序的键值对:

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

*/

void main(){
  // Map person={
  //   "name":"张三",
  //   "age":20
  // };

  // var m=new Map();
  // m["name"]="李四";
  // print(person);
  // print(m);

//常用属性:

    // Map person={
    //   "name":"张三",
    //   "age":20,
    //   "sex":"男"
    // };

    // print(person.keys.toList());
    // print(person.values.toList());
    // print(person.isEmpty);
    // print(person.isNotEmpty);

//常用方法:
    Map person={
      "name":"张三",
      "age":20,
      "sex":"男"
    };

    // person.addAll({
    //   "work":['敲代码','送外卖'],
    //   "height":160
    // });
    // print(person);

    // person.remove("sex");
    // print(person);
    print(person.containsValue('张三'));
}

forEach map where any every


void main(){

      //  List myList=['香蕉','苹果','西瓜'];
      // for(var i=0;i<myList.length;i++){
      //   print(myList[i]);
      // }

      // for(var item in myList){
      //   print(item);
      // }

      // myList.forEach((value){
      //     print("$value");
      // });

      // List myList=[1,3,4];
      // List newList=new List();
      // for(var i=0;i<myList.length;i++){
      //   newList.add(myList[i]*2);
      // }
      // print(newList);

      // List myList=[1,3,4];
      // var newList=myList.map((value){
      //     return value*2;
      // });
      // print(newList.toList());

      // List myList=[1,3,4,5,7,8,9];
      // var newList=myList.where((value){
      //     return value>5;
      // });
      // print(newList.toList());

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

      // List myList=[1,3,4,5,7,8,9];
      // var f=myList.every((value){   //每一个都满足条件返回true  否则返回false
      //     return value>5;
      // });
      // print(f);

      // set
      // var s=new Set();
      // s.addAll([1,222,333]);
      // s.forEach((value)=>print(value));

      //map
       Map person={
          "name":"张三",
          "age":20
        };
        person.forEach((key,value){
            print("$key---$value");
        });
}

函数 (略)

函数高级应用

箭头函数

匿名方法,自执行方法

int getNum(int n) {
  return n;
}

void main() {
  // print(getNum(12));

  //匿名方法
  // var printNum=(){
  //   print(123);
  // };
  // printNum();

  // 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(5);
  // print(sum);

//通过方法的递归 求1-100的和

  var sum=0;
  fn(int n){
      sum+=n;
      if(n==0){
        return;
      }
      fn(n-1);
  }

  fn(100);
  print(sum);
}

闭包

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

void main() {
  // print(a);

  // fn(){
  //   a++;
  //   print(a);
  // }
  // fn();
  // fn();
  // fn();

//局部变量
  // printInfo() {
  //   var myNum = 123;
  //   myNum++;
  //   print(myNum);
  // }

  // printInfo();
  // printInfo();
  // printInfo();

//闭包

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

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

类 对象

内置类


void main(){

    // List list=new List();  //最新版本的dart中已没法使用
    // list.isEmpty;
    // list.add('香蕉');
    // list.add('香蕉1');

    Map m=new Map();
    m["username"]="张三";
    m.addAll({"age":20});
    m.isEmpty;

    Object a=123;
    Object v=true;
    print(a);
    print(v);

}

自定义类

// 定义类
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(){

  //实例化
  // var p1=new Person();
  // print(p1.name);
  // p1.getInfo();

  Person p1=new Person();
  // print(p1.name);
  p1.setInfo(28);
  p1.getInfo();

}

构造函数

// 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(String name,int age){
//       this.name=name;
//       this.age=age;
//   }
//   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();


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

}

命名构造函数

  • dart 里面构造函数可以写多个。
/*
注意:最新版本的dart中需要初始化不可为null的实例字段,如果不初始化的话需要在属性前面加上late
*/
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() {
  // var d=new DateTime.now();   //实例化DateTime调用它的命名构造函数
  // print(d);

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

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

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

私有属性和私有方法

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();  //类里面方法的相互调用
  }
}

setter 与 getter

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

  void main(){
    Rect r=new Rect(10,4);
    // print("面积:${r.area()}");
    r.areaHeight=6;

    print(r.area);
  }
}

初始化

// Dart中我们也可以在构造函数体运行之前初始化实例变量
class Rect{
  int height;
  int width;
  Rect():height=2,width=10{
    print("${this.height}---${this.width}");
  }
  getArea(){
    return this.height*this.width;
  }
}

void main(){
  Rect r=new Rect();
  print(r.getArea());

}

静态成员, 静态方法

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();        //静态方法
        //print(this.age);     //静态方法没法访问非静态的属性
        // this.printInfo();   //静态方法没法访问非静态的方法
        // printInfo();
  }

}

main(){
  // print(Person.name);
  // Person.show();

  // Person p=new Person();
  // p.printInfo();
  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();   //已被最新的dart废弃 了解

  //  Person p=new Person('张三', 20);
  //  p?.printInfo();   //已被最新的dart废弃 了解

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

  // var p1;
  // p1='';
  // p1=new Person('张三1', 20);
  // p1.printInfo();
  // (p1 as Person).printInfo();

  //  Person p1=new Person('张三1', 20);
  //  p1.printInfo();
  //  p1.name='张三222';
  //  p1.age=40;
  //  p1.printInfo();

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

继承

  • 简单继承 extends
  • super 关键字 继承
/*
面向对象的三大特性:封装 、继承、多态
Dart中的类的继承:
    1、子类使用extends关键词来继承父类
    2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
    3、子类能复写父类的方法 getter和setter

*/
class Person {
  late String name;
  late num age;
  late String gender;
  Person(this.name,this.age);
  void printInfo() {
    print("${this.name}---${this.age}");
  }
}
class Web extends Person{
  Web(String name, num age, String gender) : super(name, age){
    this.gender=gender;
  }
   run(){
   print("${this.name}---${this.age}--${this.sex}");
  }
}

main(){

  // Person p=new Person('李四',20);
  // p.printInfo();

  // Person p1=new Person('张三',20);
  // p1.printInfo();

  Web w=new Web('张三', 12,"男");
  w.printInfo();
  w.run(); // 张三---12--男

}

复写父类的方法

  • @override 复写父类的方法
/*

面向对象的三大特性:封装 、继承、多态


Dart中的类的继承:
    1、子类使用extends关键词来继承父类
    2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
    3、子类能复写父类的方法 getter和setter

*/

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
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}");
  }
  
  work(){
    print("${this.name}的工作是写代码");
  }
}

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

子类调用父类方法

  • super 关键字
/*
面向对象的三大特性:封装 、继承、多态


Dart中的类的继承:
    1、子类使用extends关键词来继承父类
    2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
    3、子类能复写父类的方法 getter和setter

*/

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();  //子类调用父类的方法
  }
  //覆写父类的方法
         //可以写也可以不写  建议在覆写父类方法的时候加上 @override
  void printInfo(){
     print("姓名:${this.name}---年龄:${this.age}");
  }
}


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

抽象,多态,接口

抽象

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

class Dog extends Animal{
  
  eat() {
     print('小狗在吃骨头');
  }

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

  
  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();   //抽象类没法直接被实例化

}

多态

  • 多态的实现,就是通过抽象类。多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现。
abstract class Animal{
  eat();   //抽象方法
}

class Dog extends Animal{
  
  eat() {
     print('小狗在吃骨头');
  }
  run(){
    print('run');
  }
}
class Cat extends Animal{
  
  eat() {
    print('小猫在吃老鼠');
  }
  run(){
    print('run');
  }
}

main(){

  // Dog d=new Dog();
  // d.eat();
  // d.run();

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

  Animal d=new Dog();
  d.eat();  // 小狗在吃骨头

  Animal c=new Cat();
  c.eat(); // 小猫在吃老鼠

}

接口

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

  • 同样使用 implements 关键字进行实现。

/*
定义一个DB库 支持 mysql  mssql  mongodb

mysql  mssql  mongodb三个类里面都有同样的方法

*/


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

class Mysql implements Db{

  
  String uri;

  Mysql(this.uri);

  
  add(data) {
    // TODO: implement add
    print('这是mysql的add方法'+data);
  }

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

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

  }
}

class MsSql implements Db{
  
  late String uri;
  
  add(String data) {
    print('这是mssql的add方法'+data);
  }

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

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

main() {

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

}

mixins

一个类实现多个接口

  • implements 关键字
/*
Dart中一个类实现多个接口:
*/

abstract class A{
  late String name;
  printA();
}

abstract class B{
  printB();
}

class C implements A,B{
  
  late String name;
  
  printA() {
    print('printA');
  }
  
  printB() {
    // TODO: implement printB
    return null;
  }

}

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

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();
  c.printA(); // A
  c.printB(); // B
  print(c.info); // this is A
}

多种类型的混入

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

class A {
  String info="this is A";
  void printA(){
    print("A");
  }
  void run(){
    print("A Run");
  }
}

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

class C extends Person with B,A{
  C(String name, num age) : super(name, age);
}

void main(){
  var c=new C('张三',20);
  c.printInfo();
  // c.printB();
  // print(c.info);
  c.run(); // B Run
}

泛型

泛型方法

  getData<T>(T value){
      return value;
  }

void main(){

    // print(getData(21));
    // print(getData('xxx'));
    // getData<String>('你好');
    print(getData<int>(12));

}

泛型类

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

  List getList() {
    return list;
  }
}

main() {
  List list2 = new List<int>.filled(2, 0);
  list2[0] = 12;
  list2[1] = 13;
  print(list2);
}

泛型接口

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

class FileCache<T> implements Cache<T> {
  
  getByKey(String key) {
    return null;
  }
  
  void setByKey(String key, T value) {
    print("我是文件缓存 把key=${key}  value=${value}的数据写入到了文件中");
  }
}

class MemoryCache<T> implements Cache<T> {
  
  getByKey(String key) {
    return null;
  }
  
  void setByKey(String key, T value) {
    print("我是内存缓存 把key=${key}  value=${value} -写入到了内存中");
  }
}

void main() {
  // MemoryCache m=new MemoryCache<String>();
  //  m.setByKey('index', '首页数据');

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

异步

asyncawait


import 'dart:io';

getData() async {
  var result = await Future.delayed(Duration(seconds: 3), () {
    return "hello world";
  });
  return result;
}

main() {
  print("main start");

  getData();

  print("main end");
}

Futurethen


import 'dart:io';

main() {
  print("main start");

  // 2秒后执行的代码
  Future.delayed(Duration(seconds: 2), () {
    return "hello 111";
  }).then((data) {
    print(data);
  });

  // 3秒后执行的代码
  Future.delayed(Duration(seconds: 3), () {
    return "hello 222";
  }).then((data) {
    print(data);
  });

  print("main end");
}

库,系统库,第三方库

内置库

  • 请求数据
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();
}

库名冲突解决


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

    import 'package:lib1/lib1.dart';
    import 'package:lib2/lib2.dart' as lib2;


    Element element1 = new Element();           // Uses Element from lib1.
    lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.

*/


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;

*/

// import 'lib/myMath.dart' show getAge;

 import 'lib/myMath.dart' hide getName;

void main(){
//  getName();
  getAge();
}

延迟加载


/*
延迟加载

    也称为懒加载,可以在需要的时候再进行加载。
    懒加载的最大好处是可以减少APP的启动时间。

    懒加载使用deferred as关键字来指定,如下例子所示:

    import 'package:deferred/hello.dart' deferred as hello;

    当需要使用的时候,需要使用loadLibrary()方法来加载:

    greet() async {
      await hello.loadLibrary();
      hello.printGreeting();
    }

*/

异常


/*

Dart中的异常处理

    1、on 捕获指定的异常
    2、catch 捕获所有的异常
    3、rethrow 重新抛出异常
    4、throw 用来抛出异常

*/

void main() {
  try {
    test();
  } on FormatException catch (e) {
    print('main()方法捕获了异常:$e');
  } catch (e) {
    print(e);
  } finally {
    print('finally');
  }
}

void test() {
  throw new FormatException('格式化异常');
}

dart 2.13 后 新特性

空安全

/*
  Null safety翻译成中文的意思是空安全。
  null safety 可以帮助开发者避免一些日常开发中很难被发现的错误,并且额外的好处是可以改善性能。
  Flutter2.2.0(2021年5月19日发布) 之后的版本都要求使用null safety。
  ? 可空类型
  ! 类型断言

*/

String? getData(apiUrl){
  if(apiUrl!=null){
    return "this is server data";
  }
  return null;
}

// void printLength(String? str){
//   // print(str!.length);
//   if (str!=null){
//     print(str.length);
//   }
// }

void printLength(String? str){
  try {
    print(str!.length);
  } catch (e) {
     print("str is null");
  }
}

void main(args) {

//1、 ? 可空类型
  // int a=123;
  // print(a);

  // String username="张三";
  // print(username);

  // List<String> l1=["张三","李四","王五"];
  // print(l1);

  // int a=123;  //非空的int类型
  // a=null;  //A value of type 'Null' can't be assigned to a variable of type 'int'

  // String username="张三";  //非空的String类型
  // username=null;   //A value of type 'Null' can't be assigned to a variable of type 'String'.

  // String? username="张三";   // String?  表示username是一个可空类型
  // username=null;
  // print(username);

  // int? a=123;  //  int? 表示a是一个可空类型
  // a=null;
  // print(a);

  // List<String> l1=["张三","李四","王五"];
  // l1=null;  //A value of type 'Null' can't be assigned to a variable of type 'List<String>'.


  // List<String>? l1=["张三","李四","王五"];
  // l1=null;
  // print(l1);


  //调用方法
  // print(getData("http://www.itying.com"));
  // print(getData(null));

//2. ! 类型断言

  // String? str="this is str";
  // str=null;
  // print(str!.length);
  //类型断言: 如果str不等于null 会打印str的长度,如果等于null会抛出异常
  //  printLength("str");

   printLength(null);
}

late 关键字

/*
Null safety翻译成中文的意思是空安全。

late 关键字主要用于延迟初始化。

*/
class Person {
  late String name;
  late int age;
  void setName(String name, int age) {
    this.name = name;
    this.age = age;
  }
  String getName() {
    return "${this.name}---${this.age}";
  }
}

void main(args) {
  Person p = new Person();
  p.setName("张三", 20);
  print(p.getName());
}

late 接口

/*
和Java一样,dart也有接口,但是和Java还是有区别的。
  首先,dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现。
  同样使用implements关键字进行实现。
  但是dart的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。
  而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类。
  建议使用抽象类定义接口。
*/

/*
定义一个DB库 支持 mysql  mssql  mongodb
mysql  mssql  mongodb三个类里面都有同样的方法
*/

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

class Mysql implements Db{

  
  String uri;
  Mysql(this.uri);

  
  add(data) {
    // TODO: implement add
    print('这是mysql的add方法'+data);
  }

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

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

  remove(){

  }
}

class MsSql implements Db{
  
  late String uri;

  
  add(String data) {
    print('这是mssql的add方法'+data);
  }

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

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

main() {

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

required 关键字

/*
required关键词:
    最开始 @required 是注解
    现在它已经作为内置修饰符。
    主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required 参数或者该参数有个默认值。

*/
String printUserInfo(String username, {int age=10, String sex="男"}) {//行参
  return "姓名:$username---性别:$sex--年龄:$age";
}

String printInfo(String username, {required int age, required String sex}) {//行参
  return "姓名:$username---性别:$sex--年龄:$age";
}


void main(args) {
    print(printUserInfo('张三'));
    print(printUserInfo('张三',age: 20,sex: "女"));

    //age 和 sex必须传入
    print(printInfo('张三',age: 22,sex: "女"));
}

required 命名参数

/*

required关键词:
    最开始 @required 是注解
    现在它已经作为内置修饰符。
    主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required 参数或者该参数有个默认值。

*/

//表示 name 和age 是必须传入的命名参数
class Person {
  String name;
  int age;
  Person({required this.name,required this.age});  //表示 name 和age 必须传入

  String getName() {
    return "${this.name}---${this.age}";
  }
}


void main(args) {
   Person p=new Person(
     name: "张三",
     age: 20
   );
   print(p.getName());
}

required 参数可选

/*
required关键词:

    最开始 @required 是注解

    现在它已经作为内置修饰符。

    主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required 参数或者该参数有个默认值。

*/

// name 可以传入也可以不传入   age必须传入
class Person {
  String? name;   //可空属性
  int age;
  Person({this.name,required this.age});  //表示 name 可以传入也可以不传入   age必须传入

  String getName() {
    return "${this.name}---${this.age}";
  }
}

void main(args) {
   Person p=new Person(
     name: "张三",
     age: 20
   );
   print(p.getName());  //张三---20

  Person p1=new Person(
     age: 20
   );
   print(p1.getName());  //null---20
}

普通构造函数和常量构造函数

  • 普通构造函数
class Container{
  int width;
  int height;
  Container({required this.width,required this.height});
}

void main(){

  var c1=new Container(width: 100,height: 100);
  var c2=new Container(width: 100,height: 100);
  print( identical(c1, c2));  //false   c1和c2在内存中存储了2份

}
  • 常量构造函数
/*
常量构造函数总结如下几点:

  1、常量构造函数需以const关键字修饰
  2、const构造函数必须用于成员变量都是final的类
  3、如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
  4、实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象。
  5、Flutter中const 修饰不仅仅是节省组件构建时的内存开销,Flutter 在需要重新构建组件的时候,由于这个组件是不应该改变的,重新构建没有任何意义,因此 Flutter 不会重建构建 const 组件
*/

//常量构造函数
class Container{
  final int width;
  final int height;
  const Container({required this.width,required this.height});
}

void main(){

  var c1=Container(width: 100,height: 100);
  var c2=Container(width: 100,height: 100);
  print(identical(c1, c2)); //false

  var c3=const Container(width: 100,height: 100);
  var c4=const Container(width: 100,height: 100);
  print(identical(c3, c4)); //true

  var c5=const Container(width: 100,height: 110);
  var c6=const Container(width: 120,height: 100);
  print(identical(c5, c6)); //false

}
// 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象。

参考资料