美文网首页Flutter
Flutter中的Dart语法

Flutter中的Dart语法

作者: 追逐_chase | 来源:发表于2020-05-14 15:08 被阅读0次

    2.1 基础语法介绍

    使用VScode学习Dart语言,需要安装几个插件

    • Dart
    • Flutter
    • codeRunner 方便运行Dart

    必须有一个main入口函数

    
    
    //执行dart语法必须要有一个main函数
     main(List<String> args) {
      //在终端运行dart的时候可以参入参数
      //这个参数就是通过args传递的
      //终端命令 dart 名称  参数
    
      // List<String> args 支持泛型 <String> 
    
     print('hello word');
      
    }
    
    

    2.1.1 变量

    变量的声明有2种大的方式

    1.根据类型直接声明 String name = "CC"

    2.自动推导类型 var age1 = 20; *//类型自动推导,int

    var 声明变量

    const 声明常量,声明的时候必须赋值

    final也是声明常量,但是可以声明的时候不赋值,一旦赋值就不可以改变了

    
     //声明变量
     // 1.明确的声明
    // 变量类型 变量名称 = 赋值;
    String name = "cc"; 
    int age = 18;
    //拼接字符串
    print('我的名字是:${name},年龄是:${age}');
    
    //2.自动推导类型(var/final/const )
    
    var age1 = 20; //类型自动推导,int
    print(age1);
    
    // 3.final const声明常量
    
    final str = "AA";
    const str1 = "BB";
    
    print('${str},${str1}');
    // 区别:
    // const 必须赋值 常量值,赋值的内容必须是在编译期间就确定下来的
    // final 在赋值时, 可以动态获取, 比如赋值一个函数
    // final可以先声明,后赋值
    
    final person = Person("CC");
    print(person);
    
    //如果是用const来声明类的话
    // 必须是 构造器方法是const修饰才可以
    //类的内部属性必须是 final修饰
    
    const stu = Student("TTT");
    const stu1 = Student("TTT");
    //此时 stu stu1是同一个对象
    //但是当构造器 初始化的时候 name不相同就不是同一个对象 
    print(identical(stu,stu1));  // true 说明返回的是同一个对象
    
    
    
    //定义一个类Pseron
    class Person {
      String name;
      Person(String name){
        this.name = name;
      }
    }
    
    
    class Student {
      final String name;
      const Student(this.name);
    }
    
    

    2.1.2 数字类型

    对于数值来说,我们也不用关心它是否有符号,以及数据的宽度和精度等问题。只要记着整数用int,浮点数用double就行了。

    不过,要说明一下的是Dart中的intdouble可表示的范围并不是固定的,它取决于运行Dart的平台。

    // 1.整数类型
      int age = 18;
      int hexAge = 0x12;
      print(age);
      print(hexAge);
    // 2.浮点类型
     double height = 1.88;
     print(height);
    

    字符串和数字之间的转化:

    // 字符串和数字转化
    // 1.字符串转数字
     var one = int.parse('111');
     var two = double.parse('12.22');
     print('${one} ${one.runtimeType}'); // 111 int
      print('${two} ${two.runtimeType}'); // 12.22 double
    // 2.数字转字符串
     var num1 = 123;
    var num2 = 123.456;
    var num1Str = num1.toString();
    var num2Str = num2.toString();
    var num2StrD = num2.toStringAsFixed(2); // 保留两位小数
    print('${num1Str} ${num1Str.runtimeType}'); // 123 String
    print('${num2Str} ${num2Str.runtimeType}'); // 123.456 String
    print('${num2StrD} ${num2StrD.runtimeType}'); // 123.46 String
    

    2.1.3 布尔类型

    布尔类型中,Dart提供了一个bool的类型, 取值为true和false

    // 布尔类型
    var isFlag = true;
    print('$isFlag ${isFlag.runtimeType}');
    

    注意:Dart中不能判断非0即真, 或者非空即真

    Dart的类型安全性意味着您不能使用if(非booleanvalue)或assert(非booleanvalue)之类的代码。

      var message = 'Hello Dart'; 
       // 错误的写法 
        if (message) {   
         print(message) 
         }
    

    2.1.4 字符串类型

    Dart字符串是UTF-16编码单元的序列。您可以使用单引号或双引号创建一个字符串:

    // 1.定义字符串的方式
    var s1 = 'Hello World';
    var s2 = "Hello Dart";
    var s3 = 'Hello\'Fullter';
    var s4 = "Hello'Fullter";
    

    可以使用三个单引号或者双引号表示多行字符串:

    // 2.表示多行字符串的方式
    var message1 = '''哈哈哈呵呵呵嘿嘿嘿''';
    
      var str = """ 
          多个字符串,换行操作,
          1.这是一个字符串
          2.你是谁
          3.哈哈哈 
       """;
    

    字符串和其他变量或表达式拼接: 使用`${expression}, 如果表达式是一个标识符, 那么{}可以省略

    // 3.拼接其他变量
    var name = 'coderwhy';
    var age = 18;
    var height = 1.88;
    print('my name is ${name}, age is $age, height is $height');
    

    2.2集合类型

    2.2.1 List列表

    类型推导定义List列表

       // 类型推导
       var list1 = ['a','b','c'];
       //里面装的事字符串
       print(list1);
    

    明确的类型定义List列表

    
     // 明确的类型
       //明确的int类型
       List<int> list2 = [1,2,3,4];
       print(list2);
    

    2.2.2 Set集合

    Set:无序,元素不能重复的集合

      //自动推导
      var lset = {'q','w','g'};
    
       print('$lset,${lset.runtimeType}');
     //明确类型
      Set<int> set2 = {1,2,3,4,5};
    
      print(set2);
    

    利用Set的特性给list去重

      //创建一个String的列表
      List<String> names = ["张三","李四","王二","张三","王二"];
     //利用Set迭代器 泛型String 
      names = Set<String>.from(names).toList();
      print(names);
     // [张三, 李四, 王二]
    
    在这里插入图片描述

    2.2.3Map映射

    Map类似iOS中的字典

     //自动推动
      var dic = {'name':'cc','age':'18'};
    
       print('$dic,${dic['name']}');
    
      //明确类型 里面字符串和对象
       Map<String,Object> info = {'name':'TT'};
    
       print(info);
    

    2.2.4 几个中常见的操作

    长度的获取

    
    //1.获取长度  length
        print('lsit的长度:${list1.length}');
        print('Set的长度:${lset.length}');
        print('Map的长度:${info.length}'); 
    
    

    增删改查

    
    // 增加的元素的时候  注意类型要一致
      list1.add('cvb');
      print(list1);
    
      //删除
      list1.remove('a');
      list1.removeAt(0);
    
      print(list1);
    
      //是否包含摸个元素
      var isn = list1.contains('cvb');
      print(isn);
    
     //Map映射的
      //根据key获取元素
    
     print(dic['name']);
    
    // 获取所有的 entries
    print(dic.entries); // (MapEntry(name: cc), MapEntry(age: 18))
    //获取第一个
    var entry = dic.entries.first;
    print(entry.key);
    
    

    2.3 函数

    函数的基本定义

    
    返回值 函数名称(参数列表) {函数体}
    

    无参数 无返回值

    void test1(){
    
      print("无参数 无返回值");
    }
    
    
    
    int sum(num num1, num num2) {
      return num1 + num2;
    }
    
    

    2.3.1参数类型

    函数的参数可以分成两类:

    必须参数

    可选参数:命名可选参数位置可选参数

    命名可选参数: {param1, param2, ...}
    位置可选参数: [param1, param2, ...]
    

    位置可选参数 [类型 参数名]

    位置可选参数的 类型 必须是一致的

    
    void test4(String name,[int age,double height]){
      print('姓名:${name},年龄:${age},身高:${height}');
    }
    
    //位置可选参数, 位置可选参数的 类型 必须是一致的
       test4('CC',18,17.0);
    

    命名可选参数 {类型 参数名}

    
    void test5(String name,{int age, double height}){
     print('姓名:${name},年龄:${age},身高:${height}');
    }
    
    // 
    test5("TT",age:18,height:1.70);
    
    

    默认值

    只有可选参数,才可以设置默认值

    
    // 3.3函数默认值, 只有可选参数才可以设置默认值
    void test6([String name = "TT"]){
      print("name:${name}");
    }
    
    
    test6();
    
    

    将函数 赋值给一个变量

    
    void test1(){
      print("test函数");
    }
    
    var fn = test1;
      fn();
    

    函数作为参数

    
    //函数作为参数 
    void test1(){
      print("test函数");
    }
    
    void fn1(Function func){
    
      func();
    } 
    
    
    fn1(test1);
    
    
    

    函数作为参数,其函数有返回值 有参数

    
    main(List<String> args) {
    
      //调用函数 函数有返回值 可以省略的
      test((int num1, int num2) {
        
        return num1 + num2;
      });
    
    }
    
    //重命名
    typedef Calculate = int Function(int num1, int num2);
    
    
    void test (Calculate calc){
      
      //  var result =  calc (20,30);
       final result =  calc (20,30);
       print(result);
       
    
    }
    
    

    匿名函数

     (){
        print("匿名函数");
      };
    
    //函数作为参数 
    void fn1(Function func){
    
      func();
    } 
    
     //穿入一个匿名函数
     fn1((){
        print('匿名函数作为参数');
      });
    
    
    

    函数作为返回值

    
    //函数作为返回值
    void getRutern(){
      print("函数作为返回值");
    }
    
    // 返回值
     Function getFunc(){
        return getRutern;
      }
    
     var fun1 = getFunc();
      fun1();
    
    
    
     var movies = ['盗梦空间', '星际穿越', '少年派', '大话西游'];
    
      // 2.使用forEach遍历: 有名字的函数
      printElement(item) {
        print(item);
      }
      movies.forEach(printElement);
    
      // 3.使用forEach遍历: 匿名函数
      movies.forEach((item) {
        print(item);
      });
    
     // 箭头函数 函数体里面只执行一句代码,在dart里面才可以使用箭头函数
      movies.forEach((item) => print(item));
    
    

    2.4运算符

    赋值运算符 ??=

    如果name在声明的时候 没有赋值 是nil ,那么在使用 ??= 就可以赋值成功

    如果name有值, ??= 就使用原来的值

     var name = "cc";
    // 如果name在声明的时候 没有赋值 是nil ,那么在使用 ??= 就可以赋值成功
    // 如果name有值, ??= 就使用原来的值
    name ??= "TT";
    print(name); // 打印的结果是:cc
    
      name = null;
      name ??= "BB";
      print(name); // 打印的结果是: BB
    
    

    特殊运算符 ??

      // ?? 运算符类似swift中的 空盒运算符??
      //如果 temp有值 就使用temp的值
      //如果temp为null,就使用BMO
      var temp = "MM";
      var str = temp ?? "BMO";
      print(str);
    
    

    级联语法

    
    final p = Person()
      ..name = "CC"
      ..eat()
      ..test1();
    
      print(p);
    
    
    
    class  Person {
      String name;
    
      void test1(){
        print("test1...");
      }
    
      void eat(){
        print("eat ----");
      }
      
      //重写描述性方法
      @override
      String toString() {
       
        return 'name:${this.name}';
      }
    }
    

    2.5类和实例

    定义类

    使用 class

    
    main(List<String> args) {
       
       //类的定义 class
       var p = Person();
    
      print(p.name);
    
    
    }
    
    // 注意: 在定义类的时候,默认会有一个 构造器方法,没有参数
    //一旦重写构造器方法,系统自带的就失效
    class Person {
      //属性
      String name;
      //方法
      void eat(){
        print('吃东西');
      }
    
    
    }
    
    

    2.5.1 构造器

    
    main(List<String> args) {
    
      //创建实例对象,自定义 构造函数
      var p = Person("CC",18);
      print(p); //  name:CC,age:18,height:null
      //通过 命名构造函数创建对象
      var p2 = Person.withArgement("tt", 18, 1.70);
      print(p2); // name:tt,age:18,height:1.7
    
      //通过命名构造函数 Map映射 创建对象
    
      var per = Person.fromMap({"name":"BB","age":17,"height":1.8});
    
      print(per); // name:BB,age:17,height:1.8
    
    
      
    }
    
    

    自定义构造器方法 和 命名构造器函数

    
    class Person {
      String name;
      int age;
      double height;
      //自定义构造函数
      Person(String name, int age) {
        this.name = name;
        this.age = age;
      }
      //语法唐 构造函数
     // Person(this.name,this.age);
      
       // 命名构造函数
     Person.withArgement(String name, int age,double height){
       this.name = name;
       this.age = age;
       this.height = height;
     }
      
      // 命名构造函数2
     Person.fromMap(Map<String,Object> map){
       this.name = map["name"];
       this.age = map["age"];
       this.height = map["height"];
     }
      
      @override
      String toString() {
        
        return 'name:$name,age:$age,height:$height';
      }
      
     
      
    }
    
    

    2.5.1初始化表

    在 构造函数后面使用 : 跟上一个语句,来完成初始化列表

    
    // 类的 初始化列表
    
    class Person {
    // final修饰的成员变量,只能赋值一次,赋值会后不能在修改
     final String name;
     final int age;
     //final 修饰的变量,在构造函数 初始之前应该是有的值的
      
     // 初始化列表就是在 构造函数后面 使用 : 号,来初始化没有 赋值的变量
     Person(this.name,{int age}):this.age = age ?? 10 ;
    
    
    }
    
    

    注意:上面的构造函数,如果按照下面的方式写,是会报错的
    原因: 构造函数在执行大括号{},里面的内容时,已经初始变化完毕,和final是有冲突的

    Person(this.name){
     this.age = age;
    }
    
    
    

    2.5.2重定构造函数

    重定向函数 就是 用一个构造函数 调用另外一个 构造函数

    在一个构造函数中,去调用另外一个构造函数(注意:是在冒号后面使用this调用)

    
    main(List<String> args) {
      
      // 自定义构造函数
      var per1 = Person("CC", 17);
    
      print(per1); // name:CC,age:17
    
     // 命名构造函数
      var per2 = Person.formName("BB");
      print(per2); // name:BB,age:18
    
    }
    
    
    class Person {
       String name;
       int age;
    
       //自定义构造函数
       Person(String name, int age) {
         this.name = name;
         this.age = age;
       }
    
       //重定向函数 就是 用一个构造函数 调用另外一个 构造函数
      // 命名构造函数
      // name传入 在定义的构造函数, 18赋值给age
       Person.formName(String name):this(name,18);
    
    
    @override
      String toString() {
        // TODO: implement toString
        return 'name:$name,age:$age';
      }
    
    }
    
    
    

    2.5.3 常量构造函数

    常量构造函数 是当 通过构造方法创建对象,传入的参数相同,返回的事同一个对象

    条件:

    1.属性变量用 final修饰*

    2.构造器函数用const修饰*

    3.在创建 对象时使用const创建 对象*

    4.有const修饰声明的变量时,在创建对象的时候 const Person()中的const可以省略

    
    main(List<String> args) {
    
      //
      var per1 = const Person("cc");
    
      var per2 = const Person("cc");
    
      // identical 函数 判断2个对象是否为 同一个对象
      print(identical(per1, per2));
    
      // 有const修饰声明的变量时,在创建对象的时候 const Person()中的const可以省略
      const stu1 = Student("CC");
      const stu2 = Student("CC");
      
       print(identical(stu1, stu2));
    }
    
    
    
    class Person {
      
      final String name;
     
      const Person(this.name);
    
    }
    
    
    class Student {
      final String name;
      const Student(this.name);
    }
    

    2.5.4 工厂构造函数

    使用 factory 修饰,可以手动 返回一个 对象

    
    //工厂构造函数
    class  Person {
      String name;
    
     // 声明一个静态的 Map映射 字典
      static final Map<String,Person> _cache = <String,Person>{};
      //声明工厂方法
      factory Person(String name){
        
        //判断字典里面 有没有存储
        if (_cache.containsKey(name)) {
          
          return _cache[name];
        }else {
          final p = Person._instance(name);
          _cache[name] = p;
         return p;
        }
    
      }
     
      //命名构造函数
      Person._instance(this.name);
    
    
    }
    
    

    2.5.5 get和set方法

    
    main(List<String> args) {
    
      var p = Person();
      // p.name = "tt"; 不会调用 set 方法
      p.setName = "CC";
      print(p.getName);
    
      var stu = Student();
      stu.name = "SS";
    
      print(stu.name);
      stu.eat();
      
    }
    
    
    
    class Person {
      String name;
      
      //get方法 返回值是String 没有()
      String get getName {
        print("进入get方法");
        return name;
      }
    
     //Set方法
      set setName(String name){
        print("进入set方法");
        this.name = name;
        
      }
     
      void eat(){
        print("person");
      }
      
    }
    
    
    // 继承 extends
    class Student extends Person {
      
      @override
      void eat() {
        // TODO: implement eat
        super.eat();
        print("student");
      }
    
    }
    
    

    2.5.6 继承

    关键字: extends
    格式: class A类 extends B类 {} A继承与B

    
    class Animal {
    
      int age;
      //父类有自定义的构造函数方法
      Animal(this.age);
      
    }
    
    class Person extends Animal {
    
      String name;
      // 1.子类的构造方法在执行前,将隐含调用父类的无参默认构造方法(没有参数且与类同名的构造方法) (父类没有自定义构造函数)
    
      //2.如果父类没有无参默认构造方法,则子类的构造方法必须在 初始化列表 中通过super显式调用父类的某个构造方法。(父类有自定义构造函数)
      Person(String name, int age): name = name,super(age);
      
    }
    
    

    2.5.7 抽象类

    其实就是定义了方法的声明,没有实现,用abstract声明一个抽象类

    1. 抽象类不能实例化

    2. 抽象类中的抽象方法必须被子类实现, 抽象类中的已经被实现方法, 可以不被子类重写

    
    //声明一个Person抽象类
    abstract class Person {
      //声明了方法没有实现
       getName();
    }
    
    
    class Student extends Person {
      
      //给抽象类实现方法
      @override
      getName() {
        return "CC";
      }
    }
    
    //抽象类 不能实例化,但是可以间接实现
    // 使用 工厂函数 初始化 它的一个子类
    
    

    在前面的介绍中,我们知道abstract抽象类,不能实例化,但是如果可以让他实例化呢?
    1.使用 工厂函数 factory,手动返回一个
    2.external 方法的声明 和实现分离,声明,可以不实现
    3.注解 @patch, 可以在要实现的地方,实现 external声明的方法

     //声明一个抽象类
     abstract class Person {
      //声明了方法没有实现
       getName();
      // 可以返回一个 抽象实例
      //external 标识方法声明,可以实现
      external factory Person();
    }
    
    class Student extends Person {
      
      //给抽象类实现方法
      @override
      getName() {
        return "CC";
      }
    
     //会报错 这个就是告诉 可以在需要实现的地方 实现工厂函数 
     @patch factory Person()=> Student();
    }
    
    

    隐式接口

    每一个类相当于默认声明了一个接口,可以有其他的类来实现,给别人来实现的类要声明为 抽象类

    
    //main函数
    main(List<String> args) {
    
      var sup = SuperMan();
      sup.run();
      sup.fly();
      
    }
    
    //声明一个抽象类
    abstract class Person {
      void run();
    }
    
    abstract class Flyer {
     void fly();
    }
    
    // implements 实现 Person,Flyer 里面的方法,用逗号隔开
    class SuperMan implements Person,Flyer {
     
     @override
      void run() {
    
        print("超人会跑");
      }
      
      @override
      fly() {
       
        print("超人会飞");
      }
    }
    

    2.5.7 mixin混入

    1. 在通过implements实现某个类时,类中所有的方法都必须被重新实现(无论这个类原来是否已经实现过该方法)

    2. 一个类可能希望直接复用之前类的原有实现 要通过 Mixin混入,因为Dart中没有 多继承

    3. mixin可以定义声明一个类

    4. 通过mixin定义的类用于被其他类混入使用,通过with关键字来进行混入

    
    
    main(){
      var p = SuperMan();
      p.run();
      p.fly();
    }
    
    
    //使用 mixin 定义类
    mixin Runner {
      void run(){
        print("在奔跑");
      }
    }
    
    
    //mixin 定义类
    mixin Flyer{
      void fly(){
        print("会飞");
      }
    }
    
    //superMan不用再实现 fly 和 run 方法 直接可以调用
    class SuperMan with Runner,Flyer { }
    

    2.5.8 类的成员和类的方法

    
    main(List<String> args) {
    
       Person.run();
       Person.name = "CC";
      
    }
    
    
    class Person {
      static String name;
      static void run(){
        print("pppppppp");
      }
    }
    

    2.6 枚举

    
    main(List<String> args) {
      
      print(Point.x); // Point.x
    
      // 枚举的属性 
      // 1.index 表示每个枚举常量的索引, 从0开始.
      // 2.values: 包含每个枚举值的List.
      print(Point.x.index); // 0
    
      print(Point.values); // [Point.x, Point.y]
    
       var list = Point.values;
       print(list.first); // Point.x
    
      
      
    }
    
    // 枚举
    // 使用 enum定义枚举
    // 格式 enum name { }  name是枚举的名称
    
    enum Point {
      x,y
    }
    
    

    2.7泛型

    
    
    main(List<String> args) {
    
      // 1.list重视用泛型
    
      var list = [1,'CVB',1.50];
      print(list.runtimeType); // List<Object> 泛型的是Object
      
      // 限制类型
      var list1 = <String>['as','ed']; 
      print(list1.runtimeType); // List<String> 明确类型是String
    
      // 类的泛型
      var p = Person("CC",18);
      print(p.runtimeType); // Person<String, int> 泛型了String 和 int
    
    
      //泛型方法的定义
    
      T getName<T>(List<T> ts){
    
        return ts.first;
      }
    
      var res = getName(['A','b']);
      print(getName.runtimeType); // <T>(List<T>) => T
      print(res);
      
    }
    
    // 泛型 :没有明确的类型,什么时候用到 什么时候确定类型
    
    
    // T,M是泛型
    class Person<T,M> {
       T name;
       M age;
    
       Person(this.name,this.age);
    
    }
    
    
    

    相关文章

      网友评论

        本文标题:Flutter中的Dart语法

        本文链接:https://www.haomeiwen.com/subject/xobdnhtx.html