Dartb变量声明

作者: ketan9527 | 来源:发表于2019-11-03 15:23 被阅读0次

1.本篇简介

这一篇我们主要介绍Dart中变量声明的关键字,总共有以下几个关键字:var,final,const,Object,dynamic。下面我们会通过示例来介绍每个关键字的使用和特点。

2.var

2.1 示例

我们先通过以下代码,来看看var是怎么使用的:

    ```

    var a =1;// ==> 等价与 int a = 1;

    print(a);//1

    print(a is int);//true is 关键字用来判断 变量是否某类型,此段代码中 判断a是否为int类型

    var b = "ss";

    print(b);//ss

    print(b is int);//false

    ```

上面代码可以看出,var能用于声明任何一种的变量类型,但是,根据后面print函数打印的结果(is关键字处),dart 好像能推断出变量的实际类型,我们接着往下看。

    ```

    var a = 1;

    a = "ss";//报错:A value of type 'String' can't be assigned to a variable of type 'int'.

    //类型'String'的值不能赋给类型'int'的变量

    ```

明显,dart给我们报错了,String类型的值不能赋给int类型的变量(在写出代码时,as 已经标红)。

上面的代码等价于java中:

    ``

    int a = 1;

    a = "ss";

    ``` 

这样操作变量,明显是错的,dart本身也是一个强类型语言,var只是dart提供的一个语法糖,当var变量在进行编译的时候,会自动匹配到对应的实际类型,并用实际类型来替换该类型的声明。

2.2 总结

通过上面的示例,我们可以总结出var使用方法与需要注意的地方。

1.var 可以接受任何变量类型。

2.var声明的变量一旦赋值,类型确定,不能再改变量类型。

3.final 和 const

3.1示例

这里我们将 final 和 const 放在一起进行说明,因为这两个关键字有一定的异同点,首先我们通过代码来了解final和const的相同点。

```dart

final a;//错误 The final variable ';' must be initialized. 必须初始化final变量

const b;// 错误 同上

final a1 ="ss";// ==>等价于 final String a1 = "ss";

const b1 ="ss"; // ==> 等价于 const String b1 = "ss";

a1 = "sss";//错误  a final variable ,can only be set once; final变量只能设置一次

b1 = "sss";//错误 同上

final String a2 ="ss"; // ==> 等价于 final a2 = "ss"

const String b2 ="ss"; // ==> 等价于 const b2 = "ss";

final var a3 ="ss";//错误 Members can't be declared to be both 'final' and 'var'.Try removing the keyword 'var'.

  //成员不能同时被声明为“final”和“var”。尝试删除关键字“var”。

const var b3 ="ss";//错误  同上

```

通过上面的示例可以看出,final和const的相同点有:

1.final 和 const 声明变量的时候必须初始化,而且初始化后不允许修改。

2.使用final或const修饰变量时,可以省略变量具体类型如:上面的String。

3.final或const 不能与var同用。

我们再次通过代码,来看看final和const的不同点:

```dart

 // 示例1

  final finalTime =DateTime.now();//获取当前时间

  const constTime =DateTime.now();//Cannot invoke a non-'const' constructor where a const expression is expected. 不能在需要const表达式的地方调用非'const'构造函数。

//      示例2

  final finalList = [1,2,3];

  finalList[0] =3;

  print(finalList);//3,2,3

  const constList = [1,2,3];

  constList[0] =3;

  print(constList);//Cannot modify an unmodifiable list 无法修改无法修改的列表

//      示例3

  final finalList1 = [1,2,3];

  final finalList2 = [1,2,3];

  const constList1 = [1,2,3];

  const constList2 = [1,2,3];

  print(identical(finalList1, finalList2));//false  identical 用于判断两个变量是否指向同一个对象

  print(identical(constList1, constList2));//true

```      

上面代码中,分成了三个示例,每一个示例,表达了final和const的一个不同点。我们对三个示例进行分析:

  1. DateTime.now()用于获取当前的时间,是DateTime的一个命名函数,final修饰的时候并没有什么问题,但是用const进行修饰的时候,报错。不能在const表达式的地方调用非“const”构造函数。我们先看final和const的定义:

    final用于修饰在运行时有确定值的常量(运行时常量,在代码运行的时候才会被赋值,且final是惰性初始化,在运行时第一次使用前才会被初始化)

    const用于修饰在编译时有确定值的常量。(编译时常量就是在代码编译的时候,这个常量就被存入到引用它的类的常量池中了,与定义它的类没有什么关系,运行时引用编译时常量,并不会使定义这个常量的类被加载)

    那么上面的示例1中,DateTime.now()是获取当前时间的,获取当前时间必须程序运行起来才能获取到值,那么在编译期间是不能确定值的。修改构造函数的为const的前提条件是该类中的所有成员变量都要被final或const修饰。

    2.示例2定义了两个list,分别用final和const来修饰,可以看到,final修饰的list允许修改其内部的值,const修饰的list不允许修改其内部的值。表明:const的不可变性具有传递性,final的不可变性不具有传递性。

    3.示例3定义了四个list,其中两个用final修饰,两个用const修饰,identical方法用于判断两个变量是否指向对象,可以看到final修饰的两个相同的list并不指向同一个对象,const修饰的两个相同的list则指向同一个对象。表明:值相同时final在内存中会重复创建,const会引用相同的值。

以上三点就是final和const的不同点。

4.Object和dynamic

这里我们同样将Object和dynamic放在一起进行说明,因为这两个也是有一定的异同点。下面我们通过代码来展示相同点。

```dart

Object o =3;

o ="object";

print(o);//object

dynamic d =3;

d ="dynamic";

print(dynamic);//dynamic

```

上面代码中,和var截然不同的是,原本是int类型的 变量o 和 变量d,在后面都被重新赋值为String类型,并且能够输出变量而不报错,表示 Object和dynamic 能接受任意类型,并且是动态的(动态任意类型)。

我们再看下面的代码:

```dart

class Person{

    void speak(){

        print("hello world");    

      }

    @override

     void toString(){

        print("Person");    

      }

    }

    Object o = Person();

    o.toString();//Person

    o.speak();//The method 'speak' isn't defined for the class 'Object' ; speak方法没有为Object类定义

    dynamic d = Person();

    d.toString();//Person

    d.speak();//hello world

```

上面代码中,定义了一个Person类,重写了toString并定义了一个speak方法,可以看到,当变量o调用toString方法时能正常打印,但当变量o调用Person中定义的speak方法时,报错,speak方法没有为Object类定义,也就是说dart认为变量o的类型为Object。而用dynamic声明的变量d 并没有报错。让我们来看看下面的代码,看看dynamic声明的变量在什么时候会报错:

```dart

    //在上面的基础上 我们再定义一个类

    class Machine{

        void work(){

            print("hong long long");

          }

    }

    dynamic d = Person();

    d.toString();//Person

    d.speak();//hello world

    d.work();//Class 'Person' has no instance method 'work'. 类“Person”没有实例方法“work”。

```

可以看到,当我们调用Machine类中定义的work方法时,变量d 报错了,那么此时变量d的类型就是Person。

由上面的结果可以总结出Object和dynamic的不同点:

1.检查类型的时间:
1.1 Object在编译阶段检查类型。
1.2 dynamic在运行时检查类型。

2.实例类型:
2.1 Object声明的变量,最后的类型为Object(Object为所有类的基类,多态,导致Object能够用来创建不同实例的变量),所以,Object声明的变量,只能调用在Object中定义过的方法(函数)

2.2*** dynamic声明的变量,因为在运行时才会进行类型检查,所以只有在运行时才会成为对应的实例,(编译阶段不检查类型,所以出现了上述中 变量d 调用Machine类中的work方法并报错),和Object不同能调用Person方法的原因是:被dynamic修饰的变量编译器会提供尽可能多的组合,使得dynamic声明的变量能够调用尽可能多的方法(函数)***。

5.最后

在实际开发时,尽量少用dynamic,因为它容易引起运行时错误。

const 与 static 连用为静态常量。

类中的变量如果被const修饰,外界引用时,并不会导致这个类被加载,读者可以自己写一个类,并在类中定义一个静态代码块进行检测。

最后附上思维导图一张:

image

作者本人也是刚接触dart 和 flutter,写博客的原因是因为想记录学习的脚步,同时也是为了自己更加深刻的理解。如果有不对的地方,请务必指正。也欢迎大家一起学习交流。

相关文章

  • Dartb变量声明

    1.本篇简介 这一篇我们主要介绍Dart中变量声明的关键字,总共有以下几个关键字:var,final,const,...

  • 变量 声明

    let:块儿级作用域,同一作用域内,不许声明同一个变量,不能在函数内部重新声明参数,允许块儿级作用域随意嵌套ES6...

  • $ 变量声明

    声明变量的符号“$”变量名称赋予变量的值 声明了变量之后,就可以在作用域内直接调用了。

  • 变量声明

    我们要使用盒子装东西,是不是先要找到盒子,那在编程中,这个过程叫声明变量,找盒子的动作,如何表示: 声明变量语法:...

  • 变量声明

    1、变量声明 上面这段代码声明了一个类型为string的变量name。对于string类型的变量,声明之后没有赋值...

  • 变量声明

    var声明 主要特点:var是函数作用域,只针对函数声明可以多次声明同一个变量不会报错捕获变量怪异之处 let声明...

  • 变量声明

    es6声明变量的六种方法: var,function,let,const, class, import let...

  • 声明变量

    使用var声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境;在with语句...

  • 变量声明

    介绍 let和const是JavaScript里相对较新的变量声明方式。 像我们之前提到过的, let在很多方面与...

  • Go-变量

    变量 变量声明 变量的声明必须是显示的声明 声明的变量必须要在代码段使用 变量类型在后,变量名称在前面 当变量声明...

网友评论

    本文标题:Dartb变量声明

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