Dart 基础语法入门

  • Dart支持泛型,例如List表示任意类型对象组成的列表

    变量

    • 1、使用var 声明变量,可以赋予不同类型的值,var可以在运行中推导出变量的类型,确定了便不能更改类型

    • 2、使用Object,这个关键字大家应该都很熟悉,Java中的所有对象的父类就是Object,Object和var不同的点是即使赋了初始值,也可以指定别的类型,例如int,String,Num等。

    • 3、dynamic 和Object非常类似,唯一的区别就是如果你调用一个本身不存在的方法,Object会在编译器就直接报错,而dynamic则会在运行的时候才会抛出异常

      //var定义变量
      var name = 3;
      name = "Bob"; // 编译报错:A value of type 'String'can't be assigned to a variable of type 'int'.
      //Object定义变量
      Object a = 'blob';
      a = 123;
      a = [];
      // 动态定义变量
      dynamic _name = 'Bob';
      _name = 3;
      // object和dynamic的区别
      Object testa = "asd";
      // testa.substring(1);//编译失败:The method 'substring' isn't defined for the type 'Object'.
      //正确1强转 :print("Object>>>>"+(testa as String).substring(1));
      dynamic testdy = "restdy";
      print(testdy.substring(1));//编译通过

    常量

    • 常量在dart中可以用final和const来修饰
    • final包含了const的功能,区别在于
      1、final可以接受运行时的数据,const则只能接受编译时的数据
      2、const 必须给一个明确的编译常量值(即编译期间就确定的值),final 可以一开始不赋值。
      3、final 是惰性初始化,运行时第一次使用前才进行初始化
      4、const在修饰类中变量时,则必须加上static变量
    //-----第一点:-----
    final time = DateTime.now();
    // const time2 = DateTime.now();//编译报错:Const variables must be initialized with a constant value.
    //-----第二点:-----
    //正确
    const atest = 1;
    const btest = atest > 1 ? 2 : 1;
    //错误
    var atest2 = 1;
    //下面这句报错:Const variables must be initialized with a constant value
    // const btest2 = atest2 > 1 ? 2 : 1;
    //如果字符串是const 声明的编译时常量,编译时常量 (null、数字、字符串、布尔) 才可以作为该字符串字面量的插值表达式。
    // 这些在 const 声明的字符串常量中能用
    const aConstNum = 0;
    const aConstBool = true;
    const aConstString = 'a constant string';
    // 这些在 const 字符串中不能用,用 var 声明的才有用
    var aNum = 0;
    var aBool = true;
    var aString = 'a string';
    const aConstList = [1, 2, 3];
    const validConstString = '$aConstNum $aConstBool $aConstString';
    //编译出错:In constant expressions, operands of this operator
    // must be of type 'bool', 'num', 'String' or 'null'.
    // const invalidConstString = '$aNum $aBool $aString';
    var validConstString2 = '$aNum $aBool $aString $aConstList';
    print(validConstString2);
    //--第三点-----
    // const a; //编译报错: The constant 'a' must be initialized.
    final testfinal;
    testfinal = "3";
    //第四点
    class Test{
    const String name="jack";//报错提示:尝试将字段声明为
    //最终字段,或添加关键字“静态”。
    void getString(){
    const String name2="jack";
    }
    }

    5、final 只可用来修饰变量, const 关键字不仅仅用来定义常量,还可以用来创建常量值,该常量值可以赋予给任何变量。也可以将构造函数声明为 const,这种类型的构造函数创建的对象是不可改变的。
    6、const 修饰对象时,要在构造方法加const

    //5、const修饰的数组列表不能被修改
    var foo = const [1,2,3];
    // foo[0] = 3;//报错:Cannot modify an unmodifiable list
    // print("foo:{$foo}");
    //final定义的数组列表可以被修改
    final bar = [1,3,4];
    bar[0] = 9;
    print("bar:${bar}");//正确
    //一样不能被修改
    final barconst = const [];
    // barconst[0] = 9;//报错:Cannot modify an unmodifiable list
    const baz = []; // 相当于`const []`
    baz.add("value");
    print(baz);//报错:Cannot add to an unmodifiable list
    //const 修饰对象
    //const 修饰对象时,要在构造方法加const
    //否则会报:Cannot invoke a non-'const' constructor where a const expression is expected.
    const p1 = const Person('myname');
    const p2 = Person('myname'); // 右边的const 可以省略
    var p3 = const Person("myname");
    print("---------${identical(p1, p2)}");// true
    print("---------${identical(p1, p3)}");// false
    • 关于identical函数(检查两个引用是否指向同一个对象。)
    //官方说明
    var o = new Object();
    var isIdentical = identical(o, new Object()); // false, different objects.
    isIdentical = identical(o, o); // true, same object
    isIdentical = identical(const Object(), const Object()); // true, const canonicalizes
    isIdentical = identical([1], [1]); // false
    isIdentical = identical(const [1], const [1]); // true
    isIdentical = identical(const [1], const [2]); // false
    isIdentical = identical(2, 1 + 1); // true, integers canonicalizes

    关键字

    Dart 基础语法入门-每日运维

    • 带有上标1的是上下文关键字,仅在特定位置具有含义。它们是可以在任何地方作为标识符。
    • 带有上标2的单词是内置标识符。为了简化将JavaScript代码移植到Dart的任务,这些关键字在大多数地方都是有效的标识符,但它们不能用作类或类型名称,也不能用作导入模块时的前缀。
    • 带有上标3的单词是与Dart 1.0发布后添加的异步支持相关的关键字。

    part和part of

    这个关键字可以把文件分成多个文件,将一个大的lib拆分成多个小的文件

    注意part跟part of 要配套使用

    • A类
        part "B.dart"//指明BA的一部分
    
    • B类
        part of "A.dart"//指明B是属于A的一部分
    

    运算符

    Dart 基础语法入门-每日运维

    //赋值运算符
    var a = 1;
    int? b;
    print(b);//null
    b ??= 2; // 如果 b 为空的话就把 2 赋值给 b
    print(b);//2
    a += 0;
    print(a);//1
    // 算数运算符
    //a=1,b=2
    print(a + b);//3
    print(a - b);//-1
    print(a * b);//2
    print(a / b);//0.5 在java中会进行取整运算,在dart中会自动推导成小数
    print(a % b); // 取余 1
    print(a ~/ b); // 取整 0 ===>和java的取整一样
    //以下和java一样
    // a++ // 先运算再自增
    // a-- //先运算再自减
    // --a // 先自减再运算
    // ++a // 先自增再运算
    print("========关系运算符========");
    ////a=1,b=2
    //关系运算符
    print(a == b);//false
    print(a >= b);//false
    print(a "zhujiang";
    String test1(){
    return "zhujiang";
    }
    //可选命名参数
    main() {
    print(add(a: 1, b: 3));
    }
    int add({int a = 1, int b = 0}) {
    return a + b; // 输出4
    }
    //可选位置参数
    int add2(int a,[int b = 2,int c = 3]) {
    return a + b;
    }
    print(add2(1));//3
    print(add2(1,2));//3
    print(add2(1,1,3));//2
    //必选在可选参数之前
    int add2([int b = 2,int c = 3],int a) { // 报错:Expected to find ')'.
    return a + b;
    }
    int add3(int c,{int a = 1, int b = 0}) {// 报错:Expected to find ')'.
    return a + b;
    }

    匿名函数

    • 分为有参匿名和无参数匿名
    //无参
    var printFun = () => print("**无参匿名函数**");
    //有参
    var printFun2 = (name) => print("**有参匿名函数 $name**");
    printFun2("sss");

    闭包

    • Dart内也有闭包的定义,这和JavaScript相似
    Function makeAddFunc(int x) {
    return (int y) => x + y;
    }
    var makeAddFun = makeAddFunc(11);
    void main(){
    print(makeAddFun(10));//输出21
    }

    词法作用域

    • Dart 的作用域是词法作用域,跟 JavaScript 一样,在写代码的时候就确定了。
    void test1(){
    var a = 2;
    void test2(){
    var b = 3;
    print(a);
    }
    }

    逻辑控制

    // for 循环
    for (var i = 0; i 0) {
    print(while1);
    while1--;
    }
    print("======do-while======");
    // do-while
    var i = 5;
    do {
    print(i);
    i--;
    } while (i > 0);
    // do while 跟 while 的区别是即使不满足条件,do while 循环也会 do 一次;while 循环不会
    // 断言——assert
    // assert(1 2, '1>2 is wrong');//当表达式为false,抛出异常: '1 > 2': 1>2 is wrong
    print("====异常-捕获=====");
    // 异常-捕获
    try {
    // throw Error(); // 输出:No specified type, handles all error Instance of 'Error'
    //抛出异常
    // throw Exception(); // 输出 this is Unknown exception Exception
    // ('this is exception error');
    // num i = 3 / 0;
    int i = 3~/0; // IntegerDivisionByZeroException
    print(i);
    } on Exception catch (e) { //1. 需要指定异常类型时使用on
    print('this is Unknown exception $e');
    rethrow;//3. 要部分处理异常,同时允许它继续抛出异常,请使用rethrow关键字,
    // rethrow 会保留原异常的堆栈信息,而throw里面的堆栈信息会重新定位到最近的点
    // throw e;//这个堆栈信息打印就会只定位到88行。而rethrow会定位到真正错误的点,所以再次
    // 在try-catch里面抛出异常,最好使用rethrow
    } catch (e,s) {
    print('No specified type, handles all error $e');
    print('Stack trace:\n $s');
    }finally{
    print("finally "); // 一定会执行
    }
    //补充:如果有finally,finally代码块一定会执行,
    //所以finally代码块如果有return ,则会覆盖掉try/catch里面的return,
    //这点和java一样

    Dart面向对象

    类与对象

    • 构造函数
    • 命名构造函数
    • 常量构造函数
    • 工厂构造函数
    • Getter和Setter
    //dart中的构造函数
    class Point {
    num x;
    num y;
    Point(this.x, this.y);
    // String? name; // Declare instance variable name, initially null.
    // int _age = 0;
    // 2、命名式构造函数——使用初始化列表===>写法:类名.函数名():命名参数
    // Person.origin(String name,int age):this.name = name,this._age = age;
    // 命名式构造函数的另一种写法
    // Person.origin(String this.name,int this._age);
    // 3、常量构造函数
    // 使用常量构造函数,要注意两点:一是要确保所有实例变量都是final;
    // 二、构造器前面要有const关键字,且不能要有函数载体
    final String? name; //
    final int _age; //
    const Person(this.name, this._age);
    // 工厂构造函数
    static Person? instance;
    factory Person.getInstance(){
    if(instance == null){
    instance = Person("name", 31);
    }
    return instance as Person;
    }
    }

    get和set

    • 这个的好处是可以监听属性值的变换
    class Rect {
    int height;
    int width;
    Rect(this.width, this.height);
    // 手动指定 getter 的写法
    get area {
    return this.height * this.width;
    }
    // 手动指定 setter 的写法
    set h(int value) {
    print("当你调用 xx.h 时,会打印这段话,表示你已经被监听到了");
    this.height = value;
    }
    set w(int value) {
    this.width = value;
    }
    }
    void main(List args) {
    var p = Rect(10, 20);
    print(p.area);// getter
    p.h = 100;// setter
    p.w = 100;
    print(p.area);
    }

    静态成员

    Dart泛型

    • 作用:把类型延迟到使用的时候指定
    show(T a){
    print(a);
    }
    void main(List args) {
    show("hello");//"hello"
    //example2
    var p = My();
    p.say(3);//3
    }
    class My{
    say(T a){
    print(a);
    }
    }

    相关资料

    Dart官网教程
    Dart在线编辑器
    掘金中的Dart相关文章
    掘金中的Dart相关文章2:Dart从入门到放弃
    Dart关键字说明
    flutter1
    flutter2\