Dart 学习记录

本文最后更新于 2024年3月1日 下午

Dart

基本语法

1
2
3
void main(){
print("Hello");
}

变量

自动推导:var str='this is var';

指定类型:String str='this is var';

常量

const:定义需要赋值,不能修改

final:定义可以不要复制,可以赋值一次,且为运行时常量

数据类型

数字

int,double,num(包括上面两个)

字符串

string

格式化:print("$str1 str2");

拼接:print(str1+str2);

布尔

bool

集合类型:List,Map,Set

List

为了不与其他语言混淆

我一直是这样定义的:

1
2
3
var list1 = []
var list2 = [1,"12",true]
print(list2[2]);

定义List类型

1
var list3 = <int>[1,2];

List的常用属性

1
2
3
first
isEmpty
length

具体参考:https://api.dart.cn/stable/3.3.0/dart-core/List-class.html

List的方法

1
2
3
4
5
6
add() 
addAll() //加数组
sort()
insert()
remove()
any() ……

创建指定长度List

1
var zeroList = List<int>.filled(3, 0, growable: true);

遍历:

1
2
3
4
5
6
7
8
9
for(var item in list1){
print(item)
}

list1.forEach((item) => print(item));

list1.forEach((item) {
print(item);
});

操作每一个元素:

map

1
2
3
4
5
6
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
List<int> doubledNumbers = numbers.map((int number) => number * 2).toList();
//也可以用map((item){return item * 2;});
print(doubledNumbers); // 输出: [2, 4, 6, 8, 10]
}

过滤元素:

where

1
2
3
4
5
6
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
List<int> evenNumbers = numbers.where((int number) => number % 2 == 0).toList();
//也可以用where((item){return item%2==0;});
print(evenNumbers); // 输出: [2, 4]
}

条件判断:

any,every

any:只要有一个元素满足输出true

1
2
3
4
5
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
bool hasEvenNumbers = numbers.any((int number) => number % 2 == 0);
print(hasEvenNumbers); // 输出: true
}

every:每个元素满足输出true

1
2
3
4
5
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
bool allEvenNumbers = numbers.every((int number) => number % 2 == 0);
print(allEvenNumbers); // 输出: false
}

同样,set和map类型也可以使用上面的方法

Set

无重复值的List

因为是动态的,不能下标索引,也最好不要遍历

1
2
3
4
5
var str1 = new Set();
str1.addAll([1, 2]);

var list1 = str1.toList();
print(list1[1]);

Map

1
2
3
4
5
6
7
8
9
10
var person = {
"name": "azusa",
"age":"18",
"hobby":["1", "2"]
};

//或者

var p1 = new Map();
p1["name"] = "123";

Map的具体属性和方法参考:https://api.dart.cn/stable/3.3.0/dart-core/Map-class.html

类型判断

1
2
var p1 = new Map();
print(p1 is Map);

类型转换

1
2
var num1 = 12;
var snum1 = num1.toString();
1
2
3
4
var str1 = "123a";
var str2 = int.tryParse(str1); //比parse好,不会报错,只会返回null
print(str2);
print(str2.runtimeType);

语法

条件判断

if else

switch case 都与 c一样

特殊赋值语句

b??=23; 表示如果b为空的话把 23赋值给b

循环

for,while,do while和c一样

函数

main内也可以声明函数,注意作用域即可

可选参数:

1
void func1([int age = 1]) {}

匿名函数,函数作为参数传递:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void main() {
var fn = () {
print("hello1");
};

void func2(fn) {
print("hello2");
fn();
}

void func3() {
print("HELLO3");
}

func2(fn);
}

箭头函数与方法的区别:

箭头函数只有一条语句

函数可以写多条

自执行方法:

1
2
3
4
((int n){
print(n);
print('我是自执行方法');
})(12);

闭包:

1
2
3
4
5
6
7
8
9
10
11
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}

void main() {
var add2 = makeAdder(2); //返回一个函数
var add5 = makeAdder(6);

print(add2(3)); // 输出 5,保存了2
print(add5(3)); // 输出 9,保存了6
}

面向对象

类 Class

和其他语言差不多:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person{
String name="张三";
int age=23;
void getInfo(){
// print("$name----$age");
print("${this.name}----${this.age}");
}
void setInfo(int age){
this.age=age;
}
}

var p1=new Person(); //实例化

构造函数:

1
2
3
4
5
6
7
8
9
10
11
class Person{
String name='张三';
int age=20;
//默认构造函数
Person(){
print('这是构造函数里面的内容 这个方法在实例化的时候触发');
}
void printInfo(){
print("${this.name}----${this.age}");
}
}

简化版构造函数以及late关键字
像String这种不能为null的类型,如果没有初始化,就要在前面加late

1
2
3
4
5
6
7
8
9
class Person{
late String name;
late int age;
//默认构造函数的简写
Person(this.name,this.age);
void printInfo(){
print("${this.name}----${this.age}");
}
}

命名构造函数,即一个类可以写多个不同的构造函数:

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
  //Person p1=new Person('张三', 20);   //默认实例化类的时候调用的是 默认构造函数

//Person p1=new Person.now(); //命名构造函数

Person p1 = new Person.setInfo('李四', 30);
p1.printInfo();class Person {
late String name;
late int age;
//默认构造函数的简写
Person(this.name, this.age);
Person.now() {
print('我是命名构造函数');
}
Person.setInfo(String name, int age) {
this.name = name;
this.age = age;
}
void printInfo() {
print("${this.name}----${this.age}");
}

//调用:
Person p1=new Person('张三', 20); //默认实例化类的时候调用的是 默认构造函数
Person p1=new Person.now(); //命名构造函数
Person p1 = new Person.setInfo('李四', 30);

没有private,可以使用_把一个属性或者方法定义成私有。

getter,setter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyClass {
String _name;

String get name {
return _name;
}

set name(String newName) {
_name = newName;
}
}

void main() {
var myObject = MyClass();

myObject.name = 'John'; // 使用setter设置属性值
print(myObject.name); // 使用getter获取属性值
}

在Dart中,可以在构造函数体运行之前初始化实例变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MyClass {
String name;
int age;

MyClass(String initialName, int initialAge)
: name = initialName,
age = initialAge {
print('构造函数体运行之前的初始化');
print('name: $name, age: $age');
}
}

void main() {
var myObject = MyClass('John', 25);
}

类型转换:as

类型比较:is

.. 级联操作 (连缀):

1
2
3
4
5
6
Person p1 = new Person('张三1', 20);
p1.printInfo();
p1
..name = "李四"
..age = 30
..printInfo();

继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Animal{
String name="Usagi";
void printsome(){
print("${name}");
}
}

class Rabbit extends Animal{

}

void main(){
Rabbit rb = new Rabbit();
rb.printsome();
}

父类中存在构造函数,子类需要使用 Rabbit(super.name, super.age);继承

如果是命名构造函数,则可以使用Rabbit.func2(super.name, super.sex) : super.func2();来继承

子类方法覆写,加不加@override都行

子类调用父类的方法:super.func3();

抽象类

1
2
3
4
5
6
7
abstract class Shape {
double getArea(); // 抽象方法

void printDetails() {
print('This is a shape');
}
}

抽象类既可以存在抽象方法,也可也存在普通的方法

extends与implements:

extends:继承,需要实现所有抽象方法,属性和非抽象方法可以直接继承

implements:实现所有方法和属性

可以实现多个抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

abstract class A{
printA();
}

abstract class B{
printB();
}

class C implements A, B{
printA() {
print('A');
}
printB() {
print('B');
}
}

多态

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
abstract class Animal {
eat(); //抽象方法
}

class Dog extends Animal {
@override
eat() {
print('小狗在吃骨头');
}

run() {
print('run');
}
}

class Cat extends Animal {
@override
eat() {
print('小猫在吃老鼠');
}

run() {
print('run');
}
}

main() {
// Dog d=new Dog();
// d.eat();
// d.run();

// Cat c=new Cat();
// c.eat();

Animal d = new Dog();
d.eat();
// d.run(); 错误

Animal c = new Cat();
c.eat();
}

直接看这个例子就好了

mixins

通过mixin,可以不用继承就使用这些mixin类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mixin A {
void aMethod() {
print('A method');
}
}

class B {
void bMethod() {
print('B method');
}
}

class C extends B with A {
void cMethod() {
print('C method');
}
}

void main() {
C c = C();
c.aMethod(); // 使用了mixin A中的方法
c.bMethod(); // 使用了B中的方法
c.cMethod(); // 使用了C自己的方法
}

泛型

泛型方法

1
2
3
4
5
6
7
getData<T>(T value){ //不指定返回
return value;
}

T getData<T>(T value){ //指定返回类型
return value;
}

泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Box<T> {
final T value;
Box(this.value);

T openBox() {
return value;
}
}

void main() {
var box1 = Box<String>('一些字符串');
var box2 = Box<int>(100);
var box3 = Box<double>(3.14);

print(box1.openBox()); // 输出: 一些字符串
print(box2.openBox()); // 输出: 100
print(box3.openBox()); // 输出: 3.14
}

泛型接口

即在泛型类的基础上继承abstract类

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
28
29
30
31
32
33
34
35
abstract class Cache<T> {
getByKey(String key);
void setByKey(String key, T value);
}

class FileCache<T> implements Cache<T> {
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");
}
}

class MemoryCache<T> implements Cache<T> {
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是内存缓存 把key=${key} value=${value} -写入到了内存中");
}
}

void main() {
// MemoryCache m=new MemoryCache<String>();
// m.setByKey('index', '首页数据');

MemoryCache m = new MemoryCache<Map>();
m.setByKey('index', {"name": "张三", "age": 20});
}


Dart 学习记录
https://nanami.run/2024/02/19/Dart/
作者
Nanami
发布于
2024年2月19日
许可协议