[Flutter学习之Dart基础] - Dart 变量类型及声明

自上一次使用Flutter和Dart已过去了快3年了。很多基础知识已经忘记了,再加上这3年Dart和Flutter的不断更新迭代,完全跟不上了。先通过这次记笔记的方式来系统的重学一遍Flutter。但在学Flutter之前,先系统的过一遍Dart的语言。毕竟Flutter的是基于Dart去开发,只有对Dart有一定的了解,再学习Flutter的时候,尤其是一些高级用法的的时候才不至于看不懂。

初识Dart

Dart的安装是在安装Flutter的时候跟随在Flutter包内的。因此,不需要单独的去安装Dart。 在Dart语言中,你能发现Java的影子,也能看到Kotlin和JavaScript的影子。为什么这么说?因为Java中,我们可执行代码的后面都需要";"符号,在比如class类的声明方式,构造方法等,当然,也不仅仅就这么一点点,还有很多其他类似的地方,慢慢学,慢慢体会。 如:

bash 复制代码
print("Hello world!");

JavaScript的影子如:

dart 复制代码
import 'package:http/http.dart' as http;
var p = 100;
var p = "100";
print("the value of P:$p")

其实对于一个具有开发经验的人来说,尤其是有Java,kotlin或者是JavaScript经验的人来说上手Dart还是非常简单的。

Dart 变量声明

我们学习一门语言的时候,首先要了解的就是这个语言如何声明变量。

  1. 该语言的基础类型有哪些?
  2. 如何声明变量?
  3. 未初始化的变量的默认值是什么?
  4. 如何声明延迟初始化的参数?
  5. 如何声明常量?
  6. 变量的可见性如何控制?
1. 基础类型

其实大多数语言都差不多,基础类型都是:数字,浮点,布尔,字符串。只不过每个语言定义关键字略有小区别,比如大小写,或者有些语言会在数字类型再细分一些数字类型的长短之类的。那么Dart中的基础类型有哪些呢?

ini 复制代码
int i = 100;
double d = 100.0;
String s = "string";
bool b = true;

整体和其它语言没什么大的区别。唯一需要说明一下的是int类型。它和Java的int类型不一样,Java中针对数字类型的大小有比较明确的区分,如int是32位,long是64位,超出这个范围就会出现溢出。但是Dart中不会,Dart语言中的int是一个通用数字类型,默认位数是和系统保持一致,比如32位系统中默认就是有符号32位,64位系统中默认就是有符号64位。如果操作变量的值比这个64位还要更大,那Dart中也会自动改变为大数变量。所以在Dart中可以大胆的用int去表示任何整数类型的数值,不会存在溢出这个问题。double也是一样的,可以大胆的去声明浮点类型的数值。

2. 变量声明

Dart语言是一个类型安全的语言,也叫强类型语言;但即使这样,Dart中声明变量的时候,依然可以使用隐士声明,因为Dart也具有类型推断的能力。 如:

ini 复制代码
var n = 100; //这个变量会自动声明称int类型。
var s = "100"; //这个变量会自动声明称字符串类型。

但Dart语言不是弱类型语言,因此和弱类型语言还有一点区别,一旦变量类型确定了,或者说初始化了,那么该变量的类型就确定了,不可更改了。如果你强行给他赋值一个不一样的类型,编译器就会报错了。 如:

perl 复制代码
var n = 100; //这个变量会自动声明称int类型。
n = "100"; // 因为前面已经赋值了100,所以确定了n为数字类型,如果你再给他赋值一个string类型的值,那就会出现类型转换的错误:
// A value of type 'String' can't be assigned to a variable of type 'int'. (Documentation)  Try changing the // type of the variable, or casting the right-hand type to 'int'.

除了前面提到这些通过var声明变量的方式之外,还可以通过显示类型的方式声明变量。这点和Java非常相似。 如:

ini 复制代码
  int number = 100;
  String name = "Dart";
  bool isDone = true;
3. 默认值

Dart语言有一个空安全的特性,因此在声明一个变量之后,在它被使用之前必须初始化,除非它是一个可以为空的变量。也就是说如果你像前面这样的方式去声明一个变量的话,这个变量必须设置一个默认值,也就是初始化的值。否则你就得把它声明为一个可为空的变量。 如:

ini 复制代码
int count = 0;

错误用例:

scss 复制代码
int lineCount; //这样声明则表示count的值不可为空,它不会在没初始化的时候自动设置0这样的默认值。
​
if (weLikeToCount) {
  lineCount = 0;
}
print(lineCount);  //这个时候就会报错了,因为wLikeToCount这个值为false的时候,lineCount就不会被赋值了,但是它又是被声明为不可为空的变量,因此这个地方就会编译不通过了。

但间接初始化是允许的:

ini 复制代码
int lineCount;
​
if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}
​
print(lineCount); //通过前面的逻辑判断可以这个lineCount是肯定能被赋值的。
4. 延迟初始化

在我们开发过程中,我们肯定会遇到很多需要声明全局变量,但是又不想声明为可空变量,也不想给特定的默认值,那改如何解决这个问题呢? late关键字可以帮我们解决这个问题。

ini 复制代码
late String description;
void main() {
  description = 'Feijoada!';
  print(description);
}

如果使用了late这个关键字,在使用这个变量的时候,编译是不会去检查和推断你这个变量是否有初始化,一旦运行的时候发现它是未初始化的变量,则会报错。

5. 常量和不可变变量

常量也是我们日常开发中使用非常频繁的一个属性。那么在Dart中常见的两个关键字,一个是final,一个是const。那么他们分别有哪些使用场景和区别? final:通过关键字应该大致可以才到,和java其实很类似,就是一个运行时不可变的变量。 const:这个和final不太一样,这个属于编译时常量。 它们两者的区别其实和其它语言类似,编译和运行的时候,彼此所在的内存区和声明周期不一样。 普通的常见使用如:

ini 复制代码
final name = 'Bob'; 
const nickname = 'Bobby';

这两个关键字不仅仅可以声明这种基础类型,还可以用来声明数组变量等。 如:

ini 复制代码
final bar = [1,2,3,4];
const baz = [1,2,3,4];

这里有个点需要注意一下。那就是通过final声明点不可变变量是指针对变量本身不可被赋值,但是它的属性是可变的。如上声明的bar变量。如:

ini 复制代码
bar = [2,2,2,2];//这个是会报错的,因为bar是被final修饰过的
bar[2] = 4;//这样是允许的,这行代码的意思就是给bar数组中下标为2的属性赋值4。执行完之后bar的值为[1,2,4,4]

而const声明的变量则不允许,const声明的数字是期变量本身以及内部的元素都是不可以变的。如:

ini 复制代码
baz = [2,2,2,2]; //这个和final一样,都是不允许的
baz[2] = 4; // 这个和final不一样,final允许,但是const修饰的变量是不被允许的。

所以有一种场景,比如你想给某个主题声明一种色值。如:

csharp 复制代码
const primaryColors = const [
  const Color('red', const [255, 0, 0]),
  const Color('green', const [0, 255, 0]),
  const Color('blue', const [0, 0, 255]),
];

那这种场景const使用是有点冗余的。正确的使用应该是:

css 复制代码
const primaryColors = [  Color('red', [255, 0, 0]),
  Color('green', [0, 255, 0]),
  Color('blue', [0, 0, 255]),
];
6. 可见性

Dart定义属性的私有和公有,和Java不太一样。是通过"_"前缀来区分的,如:

ini 复制代码
class Person {
  String _name = "Bob"; // 私有变量
  String name = "Tony"; // 共有
}

但是Dart中的可见性没有Java中的那么严格,虽然在同一个文件中的不同类你把属性设置为私有,但是只要在同一个文件中都是可以访问的。如:

ini 复制代码
class Pet {
  String _name = "Kitte";
}
​
class Person {
  void myPet() {
    Pet pet = Pet();
    print(pet._name);
  }
}

但是如果在别的文件中去访问Pet的私有属性_name是访问不了的。

相关推荐
RichardLai888 小时前
[Flutter学习之Dart基础] - 控制语句
android·flutter
louisgeek11 小时前
Flutter Channel 通信机制
flutter
浅忆无痕15 小时前
Flutter空安全最小必备知识
android·前端·flutter
亚洲小炫风19 小时前
flutter 打包mac程序 dmg教程
flutter·macos
亚洲小炫风1 天前
flutter 桌面应用之系统托盘
flutter·系统托盘
亚洲小炫风1 天前
flutter 桌面应用之右键菜单
flutter·桌面端·右键菜单·contextmenu
louisgeek1 天前
Flutter Widget、Element 和 RenderObject 的区别
flutter
顾林海1 天前
Flutter 文本组件深度剖析:从基础到高级应用
android·前端·flutter
RichardLai882 天前
[Flutter学习之Dart基础] - Dart方法基础
flutter