dart语言学习

Dart是一门和TS类似的语言,所以在有TS基础的情况下去学习Dart会稍微容易一些。虽然说是整理学习
过程的笔记,但是我不会把Dart的文档照搬一遍,主要集中在我个人认为比较重要和常用的部分作重点记录。

语言介绍

入口函数

类似C++程序,每一个应用都有一个入口main函数,在Dart中,我们也会定义一个main函数,这个函数是整个应用的入口。

1
2
3
void main() {
print('Hello, World!');
}

late/final/const

late对我来说是一个新的概念,意指在不确定一个变量的值的情况下,可以先声明一个变量,然后在后续的代码中再赋值。
而final和const则是常量的概念,final是运行时常量,而const是编译时常量。

late是很好理解的,而final和const对我来说区别就不那么明显了。但我在dart的文档中看到这样一段话

Although a final object cannot be modified, its fields can be changed. In comparison, a const object and its fields cannot be changed: they’re immutable.

这段话的意思就很明确了,如果是final修饰的常量,那么这个常量只是无法再次被赋值,但是内部状态是可以修改的,而const则是
既无法二次赋值,也无法修改内部状态。

此外,除了二次赋值的问题以外,由于const是在编译时生效,所以当使用const去声明2个参数完全相同的实例时,会复用同一块
内存的数据,也就是说,这两个实例是完全相同的,而final则不会,final只会保证这两个实例的参数是相同的,但是实例本身是不同的。

元数据metadata

在学习使用class的时候,我发现了一个之前没有接触过的概念,那就是metadata。metadata是一种注解,可以用来描述class、
method、variable等。在Dart中,metadata是以@符号开头的,例如:

1
2
3
4
5
6
7
8
class Comp extends StatelessWidget {
const Comp({super.key});

@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

使用metadata其实是为了给代码添加更多的信息,比如说给一个class内部方法添加一个@override的metadata,那么这就说明
这个方法是重写了父类的方法。此外还有很多其他的metadata,比如@deprecated等。

有意思的mixins

Dart中的mixins是一种特殊的类,它可以被其他类继承,但是不能被实例化。mixins的作用是为了给类添加一些额外的功能。
在我写业务的期间,mixins算是非常常用的一个特性,尤其是flutter提供的一些mixin,比如SingleTickerProviderStateMixin等。

为了更好理解mixin的作用,我实际写了几个mixin放在同一个class中,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
mixin Logger {
void log(String message) {
print('[LOG]: $message');
}
}

mixin TimeLogger {
void logTime() {
print('[LOG]: ${DateTime.now()}');
}
}

class MyClass with Logger, TimeLogger {
void doSomething() {
log("执行任务中...");
}

void when() {
logTime();
}
}

void main() {
MyClass obj = MyClass();
obj.doSomething(); // 输出: [LOG]: 执行任务中...
obj.when(); // 输出: [LOG]: 2025-02-11 14:35:08.000
}

除了上面这种简单的情形,mixin还有一些其他的使用场景和特性,在这里先不展开,我会单开一篇文章来复习和总结(先立个FLag)。

扩展方法/扩展属性

在Dart中,我们可以给一个类添加一些额外的方法和属性,这些方法和属性是不需要修改原有类的代码的。这种特性叫做扩展方法和扩展属性。
这个用法我第一次见到是在一个叫做ScreenUtil的三方库里,它给num类型添加了一些方法,比如setWidthsetHeight等。

1
2
3
4
5
6
7
8
9
extension SizeExtension on num {
// 这里的this指向的是num类型的变量
double get w => ScreenUtil().setWidth(this);
double get h => ScreenUtil().setHeight(this);
double get r => ScreenUtil().radius(this);
double get dg => ScreenUtil().diagonal(this);
double get dm => ScreenUtil().diameter(this);
double get sp => ScreenUtil().setSp(this);
}

这样,我们就可以直接在num类型的变量上调用这些方法了。这个三方库的代码示例是在num类型的变量上扩展属性,那么扩展可以应用的范围是
什么呢?答案是可以扩展任何类型,包括内置类型、自定义类型等。

TBD