Dart 入门篇,记得学习呢

166 阅读6分钟

我正在参加「掘金·启航计划」

开发环境

搭建Dart 开发环境:macOS为例

以下环境配置以 mac 为例

  1. 下载并解压 Dart SDK(版本 2.13.4)

  2. 配置环境变量(保证可以访问到Dart SDK)

    sudo vim ~/.zshrc
    
    #指定 Dart SDk 安装路径
    export PATH="$PATH:/Users/whp/SDK/dart-sdk/bin
    ​
    #找到隐藏的配置文件 刷新配置
    source ~/.zshrc
    
  3. 检查 是否安装成功 (查看Dart SDk版本)

    
    dart --versin 
    

常量

常量:用于记录不可以修改的数据


const a=10 
​
final b=28 

区别

  • const是编译期常量,用于记录程序在编译期就要能确定的值
  • final 是运行时常量,用于记录程序在运行时确定的值

数据类型

var 关键字定义不同的类型,并且有类型推断的检查

Dart 空安全机制

  1. 在空安全机制下,代码中的类型默认都是非空

    除非将变量明确的声明为可空,否则它一定是非空的类型

  2. 作用:原本处于运行时的空值引用错误,将变为编译时的分析错误,从而bug会发现的更早

  3. 空安全机制下,如何定义并使用变量?

    • 变量不能为空时:指定默认值
    • 变量可以为空时:使用 " ?" 明确的指定变量可以为空

常用的数据类型

  • num (数值)

    • num ( 整数或浮点数 )

      
      num n1=10
      print(n1) // 10
      n1=10.1
      print(n1) // 10.1
      
    • int (整数)

      
      int n2=20n2=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()

函数

函数定义

  1. Dart 函数的结构

    
     返回值类型 函数名(参数1,参数2){
        函数体
        return 返回值;
     }
    
  2. 调用函数

    
    函数(参数1,参数2)
    
  1. 示例:定义计算任意两个整数之和的函数,并返回计算结果

    
    int sum(inta,intb){
      int ret=a+b
      return ret
    }
    int ret=sum(10,20)
    print(ret) //30
    
  2. 返回值 类型和参数类型都可以省略

    
    // 返回值类型参数类型都可以省略
    sum2(a,b){
      int ret =a+b
      return ret
    }
    int ret= sum2(1020)
    print(ret)//30
    
  1. 函数都有返回值,如果没有明确指定,默认返回null

    
    //函数都有返回值,如果不指定返回值类型,默认返回 null
    sum1(){
     int ret=1+2
     print(ret)
    }
    print(sum1())//null
     
    

可选命名参数

  1. 可选命名参数

    注意:可选参数必须是可以为空的

    
    返回值类型 函数名(参数1,参数2,....,{可选参数1?,可选参数2?,....}){
       函数体
       return 返回值;
    }
    

  2. 默认参数

    
    返回值类型 函数名(参数1,参数2,..., {可选参数1?=默认值1,可选参数2?=默认值2}){
     函数体
     return 返回值;
    }
    

函数对象

在Dart中,一切都是对象,函数也是对象,类型是Function

  1. 函数可作为对象赋值给其他变量

    
    void funDemo1(){
      print("funcDemo1")
    }
    ​
    Function f=funcDemo1
    f()//funcDemo1
    
  2. 函数可作为参数传递给其他函数

    
    //该函数接收一个函数作为参数
    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 返回值;
}

特点:仅在调用时,才临时创建函数对象,调用完立即释放,节省内存空间

  1. 可赋值给变量,通过变量进行调用

    
    //定义匿名函数赋值给变量并调用
    Function f=(String name){
      print(name)
    }
    f("itcast");//itcast
    
  2. 可当做参数传递给其他函数去调用(回调函数)

    
    //匿名函数当做参数传递给其他函数
    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();//我是干饭人

构造函数

创建对象时调用的函数,常用的构造函数有:

  1. 类名构造函数

    • 默认构造函数(无参数,默认隐藏)

      
      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)
    
  1. 命名构造函数

    命名构造函数,可以为类提供多个不同的构造函数

    • 定义方式:类名.函数名(){}

      
      //命名构造函数
      Person.withName(String name){
        this.name=name;
      }
      //简写命名构造函数
      Person.withName(this.name);
      //使用命名构造函数创建Person对象
      Person person=Person.withName('王五');
      
  2. 工厂构造函数

    工厂构造函数,不会直接创建对象,而是在构造函数内部通过代码来决定要创建的对象

    • 定义方式:使用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)
    

  1. 私有属性和方法

    • 私有属性和方法

      在类中定义,不对外暴露,不能被 其他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 关键字继承父类

  • 继承的特点

    1. Dart的继承是单继承,一个子类只能有一个父类
    2. 子类只会继承父类里面可见的属性和方法,不会继承私有属性和方法
    3. 子类只会继承父类默认的构造函数,不会继承 其他构造函数
    4. 子类可以重写父类的方法,也可以使用super 调用父类方法

mixin

  1. mixin 可以理解为扩展类

    • 可以为类扩展功能 ,而不需要使用继承,类似Vue里面的混入
  2. 如何定义mixin

    • 定义:mixin关键字
    
      //定义mixin类 
      mixin WalkMixin{
        double? speed;
        void walk(){
           print('walk')
        }
      }
    
    • 使用:with 关键字
    
      //人,吃饭和走路
      class Person extends Animal with WalkMixin{
        
      }
    
  3. mixin的特点

    • 可以扩展属性和方法
    • 不能被实例化,不能被继承

异步编程

能够使用 Dart 异步编程解决耗时操作阻塞程序的问题

  1. 在Web端和App中,有很多耗时操作都需要异步执行
  2. Web端的异步解决方案是 Promise,再配合 async -await 更能以同步的方式编写异步代码
  3. 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 关键字关闭变量的类型检查
  1. 特点

    1. 编码灵活,可以保存任意类型的数据
    2. 容易产生 NoSuchMethodError 的异常

泛型

泛型是指类型的不确定性,数据具体的类型可以在使用时确定

  1. 使用泛型可以限定类型

    • 使用泛型可以明确约束列表元素的类型

      
      List<String>categories=['居家''美食''100']
      
  • 使用泛型可以明确约束字典的key和value的类型

    
    Map<String,String> category={
      'id':'1',
      'name':'居家'
    }
    
  1. 使用泛型可以减少重复代码

    
    //泛型函数
    T demo<T>(T value){
      return value;
    }
    ​
    // 使用泛型函数
    String ret=demo<String>("itcast');
    print(ret)
    

异常

  1. 如何捕获异常

    • 使用关键字 try catch捕获并处理异常

    • finally:无论是否有异常都会执行到的语句块

      
      void main{
        try{
           dynamic name='itheima'
        }catch(e){
          print(e
        } finally {
          print('finally')
        }
      }
      
  2. 如何手动抛出异常:使用关键字 throw 手动抛出异常

    
    try {
       if(str!='itheima'){
         throw 'str 内容跟 itheima不匹配';
       }
    }catch(e){
        print(e)
    }