美文网首页
Dart语言基础

Dart语言基础

作者: Ray0218 | 来源:发表于2022-05-31 14:16 被阅读0次

    1.1、基本数据类型

    1.1.1、Number

    Dart 语言的 Number 有两种类型:

    int: 整数值不大于64位, 具体取决于平台

    double: 64位(双精度)浮点数

    // String -> int
    var one = int.parse('1');
    assert(one == 1);
    
    // String -> double
    var onePointOne = double.parse('1.1');
    assert(onePointOne == 1.1);
    
    // int -> String
    String oneAsString = 1.toString();
    assert(oneAsString == '1');
    
    // double -> String
    String piAsString = 3.14159.toStringAsFixed(2);
    assert(piAsString == '3.14');
    

    1.1.2、String

    Dart 字符串是一组 UTF-16 单元序列。 字符串通过单引号或者双引号创建。

     var s1 = 'Single quotes work well for string literals.';
    var s2 = "Double quotes work just as well.";
    var s3 = 'It\'s easy to escape the string delimiter.';
    var s4 = "It's even easier to use the other delimiter.";
    

    字符串可以通过 ${expression} 的方式内嵌表达式。 如果表达式是一个标识符,则 {} 可以省略。 在 Dart 中通过调用就对象的toString() 方法来得到对象相应的字符串。可以使用 + 运算符来把多个字符串连接为一个,使用连续三个单引号或者三个双引号实现多行字符串对象的创建

    var name = 'dart';
    var s1 = 's is $name';
    var s2= 's is $name' + 'language';
    var s3 = '''
    You can create
    multi-line strings like this one.
    ''';
    

    1.1.3、Boolean

    Dart 使用 bool 类型表示布尔值。 Dart 只有字面量 true and false 是布尔类型

    1.1.4、List

    var list = [1, 2, 3];
    List list2 = [1, 2, 3,'ss']; //List<dynamic> list2 = [1, 2, 3,'ss'];
    list2.remove(2);
    list2.clear();
    list2.add(2);
    list2.addAll(['a', 'b']);
    
    

    1.1.5、Map

    Map 是用来关联 keys 和 values 的对象。 keys 和 values 可以是任何类型的对象。

    //Map<String, String> 
    var gifts = {
      // Key:    Value
      'first': 'partridge',
      'second': 'turtledoves',
      'fifth': 'golden rings'
    };
    
    //Map<int, String> 
    var nobleGases = {
      2: 'helium',
      10: 'neon',
      18: 'argon',
    };
    
    //Map<dynamic, String> 
    Map nobles = {
      2: 'helium',
      10: 'neon',
      18: 'argon',
      'name' : 'dart',
    };
    

    1.2、变量

    • 任何保存在变量中的都是一个 对象 , 并且所有的对象都是对应一个 的实例。 无论是数字,函数和 null 都是对象。所有对象继承自 Object 类。
    • 使用过程中从来不会被修改的变量, 可以使用 final 或 const, 可被修改的变量是 var 或者其他类型, Final 变量的值只能被设置一次; Const 变量在编译时就已经固定
    var name = 'Bob';
    String name2 = "Bob";
    
    final name3 = 'name3';
    // final String name3 = 'name3';
    // name3 = "pop"; //The final variable 'name3' can only be set once.
    
    const name4 = 'name4';
    // name4 = "pop"; //Constant variables can't be assigned a value.
    
    final name5;
    name5 = "name5";
    // name5 = 'pop'; //The final variable 'name5' can only be set once.
    
    // const name6; //The constant 'name6' must be initialized.
    

    1.3、构造函数

    1.3.1、默认构造函数

    类里面没有显示写构造函数,默认是一个隐式的无参构造函数

    1.3.2、 普通构造函数

    指定一个类名相同的方法就是普通构造函数

    class Test{
      int a, b;
      Test(int a, int b){
        this.a = a;
        this.b = b;
      }
    }
    

    可以将上述直接简写为

    class Test{
      int a, b;
      Test(this.a, this.b);
    }
    

    1.3.3、 命名构造函数

    命名构造函数就是给构造函数添加个名字,使用命名构造函数可为一个类实现多个构造函数, 也可以使用命名构造函数来更清晰的表明函数意图:,比如从json转model时常用的fromJson就是命名构造函数, 命名构造函数不可以继承

    class Test{
      int a, b;
      Test(this.a, this.b);
      
      Test.fromJson(int a, int b){
        this.a = a;
        this.b = b;
      }
      
      //同样可以简写
      //Test.fromJson(this.a, this.b);
    }
    

    1.4 、可选参数

    函数有两种参数类型: required 和 optional。 required 类型参数在参数最前面, 随后是 optional 类型参数。可选参数可以是命名参数或者位置参数,但一个参数只能选择其中一种方式修饰。

    1.4.1、命名可选参数

    定义函数时,使用 {param1, param2, …} 来指定命名参数,默认都是可选如:

    void enableFlags({bool bold, bool hidden}) {...}
    

    使用 @required 注释表示参数是 required 性质的命名参数如:

     Scrollbar({Key key, @required Widget child})
    

    1.4.2、位置可选参数

    将参数放到 [] 中来标记参数是可选的如:

    String say(String from, String msg, [String device]) { 
      var result = '$from says $msg';  
     if (device != null) {
         result = '$result with a $device';   
        }  
     return result;
    }
    
    String result = say('Bob', 'Howdy');
    

    1.4.3、默认参数值

    在定义方法的时候,可以使用 = 来定义可选参数的默认值。 默认值只能是编译时常量。 如果没有提供默认值,则默认值为 null。

    //命名可选参数 
    void nameFlags(String name, int age,
            {bool bold = false, int height = 180}) {
          print(name + '$age' + '$bold' + '$height');
            //name18false190
    
        }
      nameFlags('name', 18, height: 190);
    
    //位置可选参数
    void enableFlags(String name, int age,
            [bool bold = false, int height = 180]) {
          print(name + '$age' + '$bold' + '$height');
             //pop18true180
        }
    
    // bold 值为 true; 
        enableFlags('pop', 18, true);
    

    1.5、抽象类用abstract关键字

    • dart抽象类主要用于定义标准, 子类可以继承抽象类,也可以实现抽象类接口
    • Dart中抽象方法不能用abstract来修饰, Dart中没有方法体的方法称为抽象方法
    • 如果子类继承抽象类,那么必须要实现抽象类里的抽象方法

    抽象类用途: 抽象类主要用于约束子类 比如子类Dog中必须实现eat和run这两个方法 这个时候父类就要用abstract来修饰(定义标准)

    abstract class Animal {
      eat(); // 抽象方法 因为没有方法体
      run();
    
      printInfo() {// 普通方法 因为有方法体
        print('我是抽象类里的一个普通方法');
      }
    }
    
    class Dog extends Animal {
      @override
      eat() {
        // TODO: implement eat
        print('小狗在吃狗粮');
      }
    
      @override
      run() {
        // TODO: implement run
        print('小狗在跑');
      }
    }
    

    1.6、继承

    • 用extends来继承其他类
    • 子类会继承父类里面可见的属性和方法 但是不会继承构造函数
    • 子类能复写父类的方法
    • 如果父类的默认构造函数 为有参数的构造函数 则子类必须要写自己的构造函数
    • 重写父类方法 直接和父类重名就行了或者用 @override
    • @override 可以写 也可以不写 建议写上
    • 子类里调用父类的方法 用super
    class Person {
      String name = '张三';
      int age = 23;
    
      void getInfo() {
        // print("姓名:$name ----- 年龄:$age");
        print('姓名:${this.name}----- 年龄:${this.age}');
        // this关键字指向了当前类的实例
      }
    }
    

    子类

    class Boy extends Person {
      String sex = 'man';
      // 如果父类的默认构造函数 为有参数的构造函数 则子类必须要写自己的构造函数
      Boy(String name, int age, String sex) : super(name, age) { 
      // super 表示  把子类初始化时传进来的参数 赋值给父类
         this.sex = sex;
      }
    
      @override  // @override 可以写 也可以不写 建议写上
      void getInfo() {
        // TODO: implement getInfo
        // super.getInfo();
        print('复写父类 ${this.name}-----${this.age}');
      } 
    }
    

    1.7、extension之扩展方法

    Dart 扩展需要关键词:extension。这个关键字只有在 Dart 版本 2.7 及其以上才支持。所以请确保你工程项目中 pubspec.yaml 文件中:

    environment:
    sdk: ">=2.7.0 <3.0.0"
    
    

    extension 的用法:

    extension <extension name> on <type> {
      (<member definition>)*
    }
    
    

    示例:

    extension StringExtension1 on String {
      //字符转换成Color对象
      toColor() {
        var hexColor = this.replaceAll("#", "");
        if (hexColor.length == 6) {
          hexColor = "FF" + hexColor;
        }
        if (hexColor.length == 8) {
          return Color(int.parse("0x$hexColor"));
        }
      }
    
      //字符转int
      parseInt() {
        return int.parse(this);
      }
    }
    
    extension DateTimeExtension on DateTime {
      toFormatString() {
        DateFormat dateFormat = new DateFormat("yyyy-MM-dd HH:mm:ss");
        return dateFormat.format(this);
      }
    }
    
    

    扩展不仅可以定义方法,还可以定义,setter,getter,operator。如果要使用这些扩展方法,只要引用导入对应的 dart 文件即可。

    import 'util/extensions.dart';//导入
    
    void main() {
      print("#90F7EC".toColor());
      print("23".parseInt());
    }
    
    

    1.8、接口 用关键词implements实现

    Flutter是没有interface的,但是Flutter中的每个类都是一个隐式的接口,这个接口包含类里的所有成员变量,以及定义的方法。如果有一个类 A,你想让类B拥有A的API,但又不想拥有A里的实现,那么你就应该把A当做接口,类B implements 类A.

    所以在Flutter中:

    1. class 就是 interface
    2. 当class被当做interface用时,class中的方法就是接口的方法,需要在子类里重新实现,在子类实现的时候要加@override
    3. 当class被当做interface用时,class中的成员变量也需要在子类里重新实现。在成员变量前加@override
    4. 实现接口可以有多个
    abstract class A {
      late String name;
      printA();
    }
    
    abstract class B {
      printB(){
    
      }
    }
    
    class C implements A,B{
      @override
      late String name;
    
      @override
      printA() {
        // TODO: implement printA
        throw UnimplementedError();
      }
    
      @override
      printB() {
        // TODO: implement printB
        throw UnimplementedError();
      }
      
    }
    

    1.9、混合 mixins (with)

    mixins的中文意思是混入,就是在类中混入其他功能。mixins是要通过非继承的方式来复用类中的代码。举个例子,有一个类A,A中有一个方法a(),还有一个类B,也想使用a()方法,而且不能用继承,那么这时候就需要用到mixins,类A就是mixins类(混入类,),类B就是要被mixins的类,对应的Dart代码如下:

    void main() {
      B b = new B();
      print(b.content);
      b.a();
    }
    
    class A {
      String content = 'A Class';
    
      void a() {
        print("a");
      }
    }
    
    class B with A {}
    

    输出是:

    A Class
    a
    

    将类A mixins 到 B,B可以使用A的属性和方法,B就具备了A的功能,但是需要强调的是:

    1. mixins的对象是类
    2. mixins绝不是继承,也不是接口,而是一种全新的特性
    3. 可以mixins多个类

    1.9.1、mixins的使用需要满足一定条件:

    1. mixins类只能继承自object
    2. mixins类不能有构造函数
    3. 一个类可以mixins多个mixins类
    4. 可以mixins多个类,不破坏Flutter的单继承

    1.9.2、on关键字

    on只能用于被mixins标记的类,例如mixins X on A,意思是要mixins X的话,得先接口实现或者继承A。这里A可以是类,也可以是接口,但是在mixins的时候用法有区别.

    class A {
      void a() {
        print("a");
      }
    }
    
    class B {
      void b() {}
    }
    
    mixin X on A {
      void x() {
        print("x");
      }
    }
    
    // on 一个类(把A作为一个类)
    // 用继承:
    class mixinsX extends A with X {}
    
    // on 的是一个接口(把A作为接口):
    // 得首先实现这个接口,然后再用mix
    
    class implA implements A {
      @override
      void a() {
        // TODO: implement a
      }
    }
    
    class mixinsX2 extends implA with X {}
    
    
    //'X' can't be mixed onto 'Object' because 'Object' doesn't implement 'A'.
    // class minxsBX extends B with X{
       
    // }
    
    

    1.10、方法冲突

    如果同时存在extends, with,implements,并且它们都定义了相同的方法名,就会存在方法冲突,我们来看下面的例子:

    class Extends {
      
      void log() {
        print('extends');
      }
      
    }
    
    mixin Mixins {
      
      void log() {
        print('mixin');
      }
      
    }
    
    mixin Mixins2 {
      
      void log() {
        print('mixin2');
      }
      
    }
    
    class Log extends Extends with Mixins, Mixins2 {}
    
    void main() {
      Log().log();
    }
    

    输出结果

    mixin2
    

    再来看一下加上了implements的情况:

    class Extends {
      
      void log() {
        print('extends');
      }
      
    }
    
    mixin Mixins {
      
      void log() {
        print('mixin');
      }
      
    }
    
    mixin Mixins2 {
      
      void log() {
        print('mixin2');
      }
      
    }
    
    class Implements {
      
      void log() {
        print('implements');
      }
      
    }
    
    class Log extends Extends with Mixins, Mixins2 implements Implements {}
    
    void main() {
      Log().log();
    }
    

    输出结果为:

    mixin2
    

    这是因为在这种情况下,它识别到我们从with和extends中获得了log()方法的能力,因此调用的是Mixins2.log()。

    假如我们对Implements#log方法进行实现:

    class Log extends Extends with Mixins, Mixins2 implements Implements {
      
      void log() {
        print("log log");
      }
    }
    

    输出的结果为:

    log log
    

    结论:

    • with修饰的会覆盖extends中修饰的同名方法。
    • with列表中后一个的会覆盖之前的。
    • extends 修饰的会覆盖implements中修饰的同名方法
    • 自身的方法会覆盖其他所有修饰中的同名方法

    相关文章

      网友评论

          本文标题:Dart语言基础

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