Dart 基础入门

参考连接markdown

Built-in Data Types

  • Numbers
    • int
    • double
  • Strings
  • Booleans
  • Lists
  • Maps
  • Runes
  • Symbols

Dart 中全部的数据类型都是 Object, 因此数据类型的默认值为 nullide

在 Dart 中定义一个变量的方法: 例如:定义一个整型的变量 age,并赋上初始值为 10函数

int age = 10;
var age = 10;
复制代码

上面这两种写法都是能够的,第二种方式会自动推断出 age 的类型为整型。oop

定义一个字符串类型的变量 name,并赋上初始值为 "jack"ui

String name = "jack";
var name = "jack";
复制代码

布尔值类型this

bool isAlive = true;
var isAlive = true;
复制代码

三目运算

var name_1;  
var name_2 = "Jack";
复制代码

和 Java 中的三目运算同样:spa

// name_1是否为空?为空 则取 name_2 不然 取值 name_1 的值
var finalName = name_1 == null ? name_2 : name_1;
复制代码

在 Dart 中判空还有一种写法,使用 ?? 来判断,以下:3d

var finalName = name_1 ?? name_2;
复制代码

表示 若是 name_1 不为空,则返回 name_1,不然返回 name_2code

Switch

switch 的条件能够是 int, String, boolcdn

for loop

List letters = ["a", "b", "c", "d"]; 
for (String letter in letters) { 
  print(letter);  
}
复制代码

For 循环执行逻辑以下: Initialize --> Condition check --> Code Execute --> Increment / Decrement

While 循环执行逻辑: Condition Check --> Code Execute --> Increment / Decrement

Do - While 循环执行逻辑: Code Execute --> Increment / Decrement --> Condition Check

Function

Functions in Dart are Object

Dart 中的函数能够做为变量,也能够做为参数传递给其余的函数。

使用简短语法定义函数中的表达式

void main() {  
  sum(2, 3);  
  
  int result = reduce(2, 3);  
  print(result);  
}  
  
void sum(int a, int b) => print("a + b = ${a + b}");  
  
int reduce(int a, int b) => a - b;
复制代码

Output:

a + b = 5
-1
复制代码

参数

Dart 中的参数分为两种,必须的可选的可选参数又包含三种分别为 位置参数(Positional)具名参数(Named)默认参数(Default)

参数的分类以下:

Required Parameters

void main() {  
  printName("Jack", "Rose");  
}  
  
// Required Parameters 
void printName(String name1, String name2) {  
  print('Name 1 is $name1, Name 2 is $name2');  
}
复制代码

可选参数

可选参数使用 [ ] 来包裹

void main() {  
  printCountries("China", "USA", "India");  
}  
  
// Optional Positional Parameters 
void printCountries(String name1, String name2, String name3) {  
  print('Name 1 is $name1');  
  print('Name 2 is $name2');  
  print('Name 3 is $name3');  
}
复制代码

Output

Name 1 is China
Name 2 is USA
Name 3 is India
复制代码

这个时候咱们想让第三个位置的参数变为可选的,就是用户调用的时候能够不传递。怎么写呢,以下:

void main() {  
  printCountries("China", "USA");  
}  
  
// Optional Positional Parameters 
void printCountries(String name1, String name2, [String name3]) {  
  print('Name 1 is $name1');  
  print('Name 2 is $name2');  
  print('Name 3 is $name3');  
}
复制代码

Output:

Name 1 is China
Name 2 is USA
Name 3 is null
复制代码

那若是咱们想让最后两个参数都变成可选的呢,也就是咱们在调用上述方法的时候只须要传递一个参数:

void main() {  
  printCountries("China");  
}  
  
// Optional Positional Parameters 
void printCountries(String name1, [String name2, String name3]) {  
  print('Name 1 is $name1');  
  print('Name 2 is $name2');  
  print('Name 3 is $name3');  
}
复制代码

Output:

Name 1 is China
Name 2 is null
Name 3 is null
复制代码

具名参数

具名参数使用 { } 来包裹 具名参数传递的时候,和参数顺序无关

当一个方法中有大量的参数的时候,咱们可使用具名参数来传递,能够防止参数传递错误:

void main() {  
  printCities("Beijing", name2: "Shanghai", name3: "Guangzhou");  
}  
  
  
// Named Parameters 
void printCities(String name1, {String name2, String name3}) {  
  print('Name 1 is $name1');  
  print('Name 2 is $name2');  
  print('Name 3 is $name3');  
}
复制代码

Output:

Name 1 is Beijing
Name 2 is Shanghai
Name 3 is Guangzhou
复制代码

咱们也能够值传递具名参数中的某一部分:

printCities("Beijing", name2: "Shanghai");
复制代码

Output:

Name 1 is Beijing
Name 2 is Shanghai
Name 3 is null
复制代码

或者

printCities("Beijing");
复制代码

Output:

Name 1 is Beijing
Name 2 is null
Name 3 is null
复制代码

默认值参数

顾名思义,默认参数就是能够为参数设置一个默认值。

void main() {  
  printNameByDefaultParameters("jack");  
}

// default parameters 
void printNameByDefaultParameters(String name1, {String name2 = "rose"}) {  
  print('name 1 is $name1');  
  print('name 2 is $name2');  
}
复制代码

上述 printNameByDefaultParameters 方法中,咱们为 name2 参数设置了默认值为 rose ,而后咱们在调用该方法的时候就能够只传递参数 name1

Output:

name 1 is jack
name 2 is rose
复制代码

固然,咱们也能够不适用默认的参数的值,咱们能够为其传递值,从而覆盖默认值:

printNameByDefaultParameters("jack", name2: "Han Meimei");
复制代码

Output

name 1 is jack
name 2 is Han Meimei
复制代码

Exception

异常处理

当程序终端或者程序崩溃的时候,这个时候就须要咱们处理异常。 咱们来看一个例子:

void main() {  
  int result = 12 ~/ 0;  
  print('The result is $result');  
}
复制代码

上述程序会抛出除数不能为0的异常:

Unhandled exception:
IntegerDivisionByZeroException
#0      int.~/ (dart:core/runtime/libintegers.dart:18:7)
...
复制代码

若是咱们知道程序会抛出哪个异常,在 Dart 中,咱们可使用 try on 来捕获,以下:

void main() {  
  try{  
    int result = 12 ~/ 0;  
  print('The result is $result');  
  } on IntegerDivisionByZeroException {  
    print('Cannot devide by zero');  
  }  
}
复制代码

输出:

Cannot devide by zero
复制代码

若是咱们不知道程序会抛出什么异常,使用 try catch 来捕获:

try{  
  int result = 12 ~/ 0;  
  print('The result is $result');  
} catch (e) {  
  print('The exception is $e');  
}
复制代码

Output:

The exception is IntegerDivisionByZeroException
复制代码

那若是咱们想知道在抛出异常以前发生了什么,可使用 Stack Trace 以下:

try{  
  int result = 12 ~/ 0;  
  print('The result is $result');  
} catch (e, s) {  
  print('The exception is $e');  
  print('Stack Trace \n $s');  
}
复制代码

Output:

The exception is IntegerDivisionByZeroException
Stack Trace 
 #0      int.~/ (dart:core/runtime/libintegers.dart:18:7)
#1      main (file:///Users/liusilong/Dev/Flutter/workspace/DartDemo/src/youtube/exception/Demo1.dart:24:21)
#2      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:289:19)
#3      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
复制代码

Finally

不管异常是否抛出,finally 语句块总会被执行:

try{  
  int result = 12 ~/ 0;  
  print('The result is $result');  
} catch (e) {  
  print('The exception is $e');  
}finally{  
  print('finally is always executed');  
}
复制代码

Output:

The exception is IntegerDivisionByZeroException
finally is always executed
复制代码

上述代码即便不抛出异常,finally 语句块中仍是会被执行:

try{  
  int result = 12 ~/ 3;  
  print('The result is $result');  
} catch (e) {  
  print('The exception is $e');  
}finally{  
  print('finally is always executed');  
}
复制代码

Output:

The result is 4
finally is always executed
复制代码

自定义异常

下面来定义一个方法,该方法不能接受小于 0 的参数,而后咱们自定义一个异常,来捕获传入该方法的参数是否小于 0 。

// 自定义异常
class MyException implements Exception {  
  String errorMsg() {  
    return "count 不能小于0";  
  }  
}

// counter 参数不能小于 0
void enterCounter(int counter) {  
  if(counter < 0) {  
    throw MyException();  
  }  
}

// 调用
try {  
  enterCounter(-2);  
} catch(e) {  
  print(e.errorMsg());  
}
复制代码

Output:

count 不能小于0
复制代码

面向对象

定义一个类

下面咱们来定义一个 Student 类,并声明一些实例变量和实例方法:

class Student {  
  // 默认值为 null 
  int id = 7;  
  // 默认值为 null 
  String name;  
  
  void study(){  
    print('${this.name} is now studying');  
  }  
  
  void sleep(){  
    print('${this.name} is now sleeping');  
  }  
}
复制代码

接下来咱们实例化一个 Student 而后为其属性赋值,并调用其方法:

void main() {  
  var stu = Student();  
  stu.id = 8;  
  stu.name = "jack";  
  print('${stu.id} and ${stu.name}');  
  stu.study();  
  stu.sleep();  
}
复制代码

Output:

8 and jack
jack is now studying
jack is now sleeping
复制代码

定义构造函数

默认构造函数

同 Java 同样,在 Dart 中,一个类也会有一个默认的无参的构造函数,咱们也能够将其定义出来:

// default constructor 
Student() {  
  print('This is default constructor');  
}
复制代码

带有参数的构造函数

// 带有参数的构造方法 
Student(int id, String name) {  
  this.id = id;  
  this.name = name;  
}
复制代码

默认构造方法和带有参数的构造方法不能同时存在,不然在编译期就会报错,以下:

参数化构造函数

通常状况下,咱们的在构造方法中传递的参数会给当前类的实例变量赋值如:this.id = id,这个时候,咱们能够直接使用参数化构造函数,以下:

// 参数化构造函数
Student(this.id, this.name);
复制代码

那么,若是咱们在一个类中先要定义多个构造方法怎么办,这个时候可使用 命名构造函数

咱们在构造方法中一样可使用具名参数,以下:

void main(){  
  var p = Person("Jack");  
  p.getInfo();  
  
  var p2 = Person("Rose", age: 18);  
  p2.getInfo();  
}

class Person{  
  String name;  
  int age;  
  
  Person(this.name, {this.age});  
  
  void getInfo(){  
    print('name is $name, age is $age');  
  }  
}
复制代码

Output:

name is Jack, age is null
name is Rose, age is 18
复制代码

命名构造函数

// 参数化构造函数 
Student(this.id, this.name);  
  
Student.myConstructor(int id) {  
  this.id = id;  
  this.name = "Jack";  
}  
  
Student.anotherConstructor(String name) {  
  this.id = 10;
  this.name = name;
}
复制代码

调用以下:

void main() {
  var stu1 = Student(8, "jack");  
  print('${stu1.id} and ${stu1.name}');  
  
  var stu2 = Student.myConstructor(7);  
  print('${stu2.id} and ${stu2.name}');  
  
  var stu3 = Student.anotherConstructor("Rose");  
  print('${stu3.id} and ${stu3.name}');  
}
复制代码

Output:

8 and jack
7 and Jack
10 and Rose
复制代码

Getter 和 Setter

默认的 Getter 和 Setter

下面咱们仍是定义一个 Student 类,里面有 nameage 两个属性:

class Student {  
  String name;  
  int age;  
}
复制代码

接着咱们来实例化出一个 Student 的实例,而且为其属性赋值:

void main() {  
  var stu = Student();  
  // 调用默认的 Setter 方法设置 name 
  stu.name = "Jack";  
  // 调用默认的 Getter 方法获取 name 
  print('name is ${stu.name}');  
}
复制代码

注意:上述代码中,咱们分别调用了默认的 Setter 方法和 Getter 方法。

Output:

name is Jack
复制代码

自定义的 Getter 和 Setter

下面咱们在 Student 类中新添加一个属性为 address,咱们来自定义这个属性的 getter 和 setter 方法:

class Student {  
  String name; // 默认的 getter 和 setter 
  int age; // 默认的 getter 和 setter 
  
  // new line 
  String address; // 自定义的 getter 和 setter 
 
  set setAddress(String address) {  
    this.address = address;  
  print('调用了 address 的 setter 方法,值为 $address');  
  }  
  
  get getAddress {  
    print('调用了 address 的 getter 方法');  
  return address;  
  }  
}
复制代码

调用

stu.setAddress = "China";  
print('stu address is ${stu.getAddress}');
复制代码

Output:

调用了 address 的 setter 方法,值为 China
调用了 address 的 getter 方法
stu address is China
复制代码

继承

和 Java 中的继承相似,Dart 中也是使用 extends 关键字来实现继承,一样,也能够实现方法重载

下面例子中,咱们定义一个父类 Animal,子类 Dog 来演示他们之间的继承关系以及方法重载的实现:

void main() {  
  var dog = Dog();  
  dog.bark();  
  dog.eat();  
}

// 父类 
class Animal {  
  void eat() {  
    print('Animal is eating');  
  }  
}

// 子类 
class Dog extends Animal {  
  // 方法重载 
  void eat() {  
    // 经过 super 调用父类方法 
  super.eat();  
  print('Dog is eating');  
  }  
  
  void bark() {  
    print('Brak!');  
  }  
}
复制代码

Output:

Brak!
Animal is eating
Dog is eating
复制代码

继承中的构造方法

通常状况下,若是父类没有有参构造方法,那么咱们能够直接这样:

// 父类
class Animal {  
  String color;  
  // 默认的构造方法 
  Animal() {}  
}  

// 子类
class Dog extends Animal {  
  final String name;  
  // 带有一个参数的构造方法 
  Dog(this.name):super() {}  
}
复制代码

上述状况中,Animal 类中的构造方法没有参数,咱们在 Dog 类中能够将 Dog(this.name):super() 后面部分省略,写为Dog(this.name)

那么若是父类中有参数的状况下,上述 Dog 类中的写法就会报错了,以下:

提示大概意思就是在父类中找不到一个包含0个参数的构造方法,咱们以前也说过,默认的构造方法和带有参数的构造方法不能同时存在。

因此咱们能够这样写:

class Animal {  
  String color;  
  
  Animal(String color) {}  
}  
  
class Dog extends Animal {  
  final String name;  
  
  Dog(this.name, String color) : super(color) {}  
}
复制代码

一样的,咱们也能够在子类中使用命名构造方法

class Dog extends Animal {  
  final String name;  
  
  Dog(this.name, String color) : super(color) {}  
  
  Dog.myDog(this.name): super("White"){  
  
  }  
}

复制代码

咱们在实例化 Dog 类的时候能够这样:

void main() {  
  var dog1 = Dog("petter", "Blcak");  
  
  var dog2 = Dog.myDog("Hello");  
}
复制代码

固然,若是父类中有命名构造方法,咱们在子类中构造方法中去调用父类的命名构造方法:

class Animal {  
  String color;  
  
  Animal(String color) {}  
  
  Animal.myAnimal() {}  
}  
  
class Dog extends Animal {  
  final String name;  
  
  Dog(this.name, String color) : super(color) {}  
  
  Dog.myDog(this.name) : super("White") {}  
  
  // 调用父类的 命名构造 方法
  Dog.smallDog(this.name) : super.myAnimal() {}  
}

复制代码

注意:

默认状况下,子类中的构造方法调用的是父类的无参构造方法 父类的构造方法老是在子类的构造方法以前调用 若是在父类中没有默认构造方法(无参构造方法),那么须要咱们手动调用父类中的某一个构造方法

抽象类和抽象方法

和 Java 中的抽象类同样,Dart 中的抽象类也是使用 abstract 关键字类修饰。如: abstract class shape{} 抽象类不能直接被实例化,须要实现一个子类来继承它。 抽象类中能够包含抽象方法和非抽象方法。抽象方法不能包含方法体且子类必须实现,非抽象方法能够包含方法体且子类能够重写。 抽象类中也能够定义的实例变量。 抽象方法只能定义在抽象类中。

void main() {
  var rect = Rectangle();
  rect.draw();
  rect.drawShape();
}

// 抽象类
abstract class Shape {
  // 定义实例变量
  int x;
  int y;
  
  // 非抽象方法,子类能够重写
  void drawShape() {
    print('draw shape');
  }

  // 抽象方法,子类必须实现
  void draw();
}

// 子类
class Rectangle extends Shape {

  // 实现父类的抽象方法(必选)
  @override
  void draw() {
    // TODO: implement draw
    print('draw Rectangle...');
  }

  // 重写父类的方法(可选)
  @override
  void drawShape() {
    // TODO: implement drawShape
    super.drawShape();
    print('rectangle drawshape');
  }
}
复制代码

Output:

draw Rectangle...
draw shape
rectangle drawshape
复制代码

接口

Java 中的接口是使用 Interface 关键字类修饰一个类,可是 Dart 中没有 Interface 关键字。Dart 中的接口依然是使用 class 类定义:

void main() {
  var b = B();
  b.hello();
  b.hi();
}

class A {
  void hello() {
    print('A hello');
  }
}

class C {
  void hi() {
    print('C hi');
  }
}

// class B 实现了 接口 A,C
class B implements A, C {
  @override
  void hello() {
    // TODO: implement hello
    print('B hello');
  }

  @override
  void hi() {
    // TODO: implement hi
    print('B hi');
  }
}

复制代码

Output:

B hello
B hi
复制代码

那么咱们在实现的接口方法中能不能使用 super.hello() 呢?

如上图,是不能够的,大概意思就是 hello 方法在父类型中是抽象的。

若是咱们将 implements 改成 extends 以后就能够了。

总结: Dart 没有特定的语法来声明一个接口。 Dart 中的接口就是一个普通的类。 当你须要在子类中从新实现父类中的全部方法的时候,可使用接口。 在接口的实现类中,会被强制要求实现父类中的全部方法。 能够implements多个类,可是只能 extends 一个类。

静态方法和变量

和 Java 中的静态变量相似,Dart 中的静态变量也是经过 static 关键字来声明,经过 类名.变量名 来访问:

void main() {
  print(Circle.pi);
}

class Circle {
  // 定义一个静态变量
  static double pi = 3.14;
}
复制代码

Output:

3.14
复制代码

可是,在 Dart 中若是咱们使用类的实例去访问该类中的静态变量,编译时就会报错:

大概意思就是静态变量不能经过实例来访问。

一样的,静态方法也是经过 static 关键字类声明,经过 类名.方法名 来调用; 一样的,静态方法也不能经过实例来访问。

void main() {
  // 访问静态变量
  print(Circle.pi);
  // 调用静态方法
  Circle.calculateAre();
}

class Circle {
  // 定义静态变量
  static double pi = 3.14;

  // 定义静态方法
  static void calculateAre() {
    print('some code');
  }
}
复制代码

Output:

3.14
some code
复制代码

静态方法中只能访问静态变量和静态方法,不能访问实例变量或者实例方法。

总结:

静态变量也被称为 类变量 静态方法也被称为 类方法 静态变量都是懒加载的,意思就是当你在程序中使用到的时候该静态变量才会被初始化。 静态变量或者静态方法与类的实例无关,它们都属于类自己,因此我么在静态方法中不能使用 this 关键字 在静态方法中,咱们只能访问静态方法或者静态变量,不能访问该类中的实例变量或者实例方法

高阶函数和 Lambda 表达式

在 Dart 中,方法也是一个对象 Lambda 是一个没有方法名的方法

下面咱们来看看示例:

void main() {
  // 普通方法调用
  addTwoNumbers(2, 3);

  // 没有返回值的 Lambda
  Function addTwoNumbersByFunction = (int a, int b) {
    var sum = a + b;
    print('$sum');
  };

  addTwoNumbersByFunction(2, 3);

  // 带有返回值的 Lambda
  var sum = (int a, int b) {
    return a + b;
  };

  print('${sum(3, 4)}');
}

void addTwoNumbers(int a, int b) {
  var sum = a + b;
  print('$sum');
}
复制代码

Output:

5
5
7
复制代码

咱们还可使用另一种简短的语法来表示 Lambda,使用 => 来表示

void main(){
    // 使用简短语法声明没有返回值的 Lambda
    Function addTwoNumbersWithArrows = (int a, int b) => print('${a + b}');

    // 调用
    addTwoNumbersWithArrows(3, 8);
      
      
    // 使用简单语法声明带有返回值的 Lambda
    var sumWithArrows = (int a, int b) => a + b;
    // 调用
    print('${sumWithArrows(3, 7)}');
}
复制代码

Output:

11
10
复制代码

高阶函数

高阶函数的定义

  • 能够接受一个 Function 做为参数的函数
  • 能够返回一个 Function 的函数
  • 以上二者都容许

下面咱们来写一个用于四则运算的高阶函数:

void main() {
  var plusResult = arithmetic(12, 3, (a, b) => a + b);
  var reduceResult = arithmetic(12, 3, (a, b) => a - b);
  var multiplyResult = arithmetic(12, 3, (a, b) => a * b);
  var divideResult = arithmetic(12, 3, (a, b) => a / b);

  print('plus result is $plusResult');
  print('reduce result is $reduceResult');
  print('myltiply result is $multiplyResult');
  print('divide result is $divideResult');
}

// 接受一个 Function 参数,而且返回了一个 Function
double arithmetic(double a, double b, Function function) {
  return function(a, b);
}
复制代码

上述代码中 arithmetic 方法接受了一个 Function,而且将其做为返回值返回; 而参数 Function 是接受两个 double 类型的参数。

咱们在上一小节中讲到 高阶函数 可使用没有名称的方法来表示也可使用 Lambda 来表示。

上述代码中使用的是 Lambda 做为高阶函数进行传递的,那么若是咱们使用没有名称的方法来表示,以下:

var modelResult = arithmetic(12, 3, (a, b) {
    return a % b;
  });
  print('model result is $modelResult');
复制代码

Output:

plus result is 15.0
reduce result is 9.0
myltiply result is 36.0
divide result is 4.0
model result is 0.0
复制代码

Collections

固定长度的 List

咱们来声明一个长度为 5 的整型 List

定长的集合在被定义以后,长度就不能被改变

void main() {
  // 声明一个固定长度的集合
  List<int> numList = List(5);
  // 添加元素
  numList.add(9);
  // 删除元素
  numList.remove(9);
  // 删除指定位置上的元素
  numList.removeAt(0);
  // 清空集合
  numList.clear();
}
复制代码

那么若是咱们只想上述代码以后会怎样呢?答案是会报错,由于上述代码中的4中操做在固定长度的集合中都不支持。

Output:

Unhandled exception:
Unsupported operation: Cannot add to a fixed-length list
...
复制代码

这里顺带提一下,上述代码中咱们知道了会抛出 Unsupported 异常,那么根据前面的知识,咱们可使用 try..on.. 来捕获,就当复习一下:

void main() {
  try {
    // 声明一个固定长度的集合
    List<int> numList = List(5);
    // 添加元素
    numList.add(9);
    // 删除元素
    numList.remove(9);
    // 删除指定位置上的元素
    numList.removeAt(0);
    // 清空集合
    numList.clear();
  } on UnsupportedError {
    print('操做不支持...');
  }
}
复制代码

Output:

操做不支持...
复制代码

那么回到咱们的问题,固定长度的集合要怎么添加删除元素呢?以下:

void main() {
  // 声明一个固定长度的集合
  List<int> numList = List(5);

  numList[0] = 1;
  numList[1] = 2;
  numList[2] = 3;
  numList[3] = 4;
  numList[4] = 5;

  print('遍历元素:');
  for (int value in numList) {
    print(value);
  }

  print('----更新第一个元素为 10------');

  numList[0] = 10;

  print('遍历元素:');
  numList.forEach((value) => print(value));

  print('----将第一个元素置为NULL---');

  numList[0] = null;

  print('遍历元素:');
  for (int i = 0; i < numList.length; i++) {
    print('${numList[i]}');
  }
}
复制代码

上述代码中,咱们使用了索引的方式来给固定长度的 List 赋值,并使用三种方式来遍历,第一种为 for..in ;第二种为 Lambda 表达式;第三种为常规的 for 循环

Output:

遍历元素:
1
2
3
4
5
----更新第一个元素为 10------
遍历元素:
10
2
3
4
5
----将第一个元素置为NULL---
遍历元素:
null
2
3
4
5
复制代码

动态长度的 List

咱们直接看示例:

void main() {
  // 动态长度的 集合
  List<int> list = List();

  list.add(1);
  list.add(2);

  list.forEach((value) => print('$value'));
  print('');
  
  list.removeAt(0);
  list.forEach((value) => print('$value'));
  print('');
  
  list.add(3);
  list[0] = null;
  list.forEach((value) => print('$value'));
}
复制代码

Output:

1
2

2

null
3

复制代码

还有一种声明方法:

// 这样也是一个动态的集合
  List<String> letterList = ["A", "B", "C"];

  letterList.add("D");
  letterList.add("E");

  letterList.forEach((letter) => print('$letter'));
复制代码

Output:

A
B
C
D
E
复制代码

Set

Set 是无序的;Set 是不容许添加剧复元素;Set 不能使用下标来获取里面里面的元素,由于它是无序 的。

void main() {
  // 方式一:
  Set<String> letterSet = Set.from(["A", "B", "C"]);
  letterSet.add("D");
  letterSet.add("E");
  // 重复的元素将被忽视
  letterSet.add("A");

  // 使用 for..in.. 遍历 Set
  for (String letter in letterSet) {
    print('$letter');
  }

  print('');
  
  // 方式二:
  Set<int> numSet = Set();
  numSet.add(0);
  numSet.add(1);
  numSet.add(2);

  // 使用 Lambda 遍历 Set
  numSet.forEach((value) => print('$value'));
}
复制代码

Output:

A
B
C
D
E

0
1
2
复制代码

Map

Dart 中 Map 的特性和 Java 中的相似,都是以键值对的形式存放,Map 中的键是惟一的,可是值能够重复,Map 也是无序的。

下面看看 Dart 中 Map 的基本操做:

void main() {
  Map<String, String> letterMap = Map();
  letterMap["a"] = "A";
  letterMap["b"] = "B";
  letterMap["c"] = "C";

  // 检查是否存在某个 key
  letterMap.containsKey("a");
  // 更新某个 key 对应的 value,注意 value 为一个 Lambda 表达式
  letterMap.update("a", (value) => "${value}AA");

  // 获取 Map 的长度
  letterMap.length;
  // 删除 Map 中的某个元素
  letterMap.remove("c");
  // 清空 Map
  letterMap.clear();

  // 遍历全部的 key
  for (String key in letterMap.keys) {
    print('$key');
  }

  print('');

  // 遍历全部的 value
  for (String value in letterMap.values) {
    print('$value');
  }

  print('');

  // 遍历全部的 key-value
  letterMap.forEach((key, value) => print('$key == $value'));
}
复制代码

上述代码中使用的是构造方法的方式来建立 Map,咱们还可使用一下方式来建立:

Map<String, int> studentScoreMap = {
    "Jack": 90,
    "Rost": 100,
    "Mary": 30,
    "LiLei": 56
  };

  studentScoreMap.forEach((name, source) => print('$name == $source'));
复制代码

Output:

Jack == 90
Rost == 100
Mary == 30
LiLei == 56
复制代码

Callable

Callable 能让咱们像调用方法同样调用某个类,不过咱们在类中须要实现 call 方法:

void main() {
  var personOne = Person();
  var info = personOne("Jack", 18);
  print('$info');
}

class Person {
  // 实现 call 方法
  String call(String name, int age) {
    return "$name is $age years old";
  }
}
复制代码

Output:

Jack is 18 years old
复制代码

若有错误,还请指出。谢谢!!!

相关文章
相关标签/搜索