Dart重要基础知识点

102 阅读10分钟

Dart 中的一些重要知识点,包括函数、运算符、控制流、异常、类、泛型、库和可见性、异步支持、生成器、可被调用的类、Isolate、typedefs、元数据、变量及重要关键词的详细解释。

变量 (Variables)

声明方式

  • var: Dart 提供了一种动态类型的变量声明方式,使用 var 时,编译器会根据赋值推断变量的类型,但类型一旦推断出来,就无法更改。

    dart
    复制代码
    var name = 'Dart'; // name 被推断为 String 类型
    // name = 42; // 错误:无法将 int 赋值给 String
    
  • dynamic: 使用 dynamic 时,变量的类型在运行时确定,可以随时改变类型。虽然提供了灵活性,但会失去编译时的类型检查。

    dart
    复制代码
    dynamic anything = 'Dart';
    anything = 42; // 合法
    
  • Object: Dart 中所有类的基类。可以用于保存任何类型的值,但仍然保留一些类型安全性。

    dart
    复制代码
    Object anything = 'Dart';
    anything = 42; // 合法
    

常量

  • final: 用于定义运行时常量。final 变量只能赋值一次,且必须在运行时初始化。可以延迟初始化(如在构造函数中)。

    dart
    复制代码
    final name = 'Dart'; // 在第一次使用时初始化
    final DateTime now = DateTime.now(); // 运行时常量
    
  • const: 用于定义编译时常量。const 变量在编译时就必须初始化,且值不可变。

    dart
    复制代码
    const pi = 3.14159; // 编译时常量
    const List<int> numbers = [1, 2, 3]; // 不可变列表
    

final 与 const 的异同

  • 异同:

    • final 变量可以在运行时初始化,而 const 变量必须在编译时初始化。
    • const 可以创建编译时的常量对象,final 不能。
    • const 可用于构造函数,以创建不可变对象,而 final 则用于变量声明。
    dart
    复制代码
    final now = DateTime.now(); // 合法
    const now = DateTime.now(); // 非法,不能在编译时确定
    

函数 (Functions)

定义与调用

  • 命名函数: Dart 中的函数可以有返回值类型和参数类型。

    dart
    复制代码
    int add(int a, int b) {
      return a + b;
    }
    
  • 匿名函数 (Lambda 表达式) : 也称为闭包,匿名函数可以捕获范围内的变量。

    dart
    复制代码
    var multiply = (int a, int b) => a * b;
    
  • 可选参数: Dart 支持位置可选参数和命名可选参数,可以为其提供默认值。

    dart
    复制代码
    // 位置可选参数
    String greet(String name, [String title = '']) {
      return 'Hello $title $name';
    }
    
    // 命名可选参数
    void printInfo({String? name, int? age}) {
      print('Name: $name, Age: $age');
    }
    
  • 高阶函数: 函数可以作为参数传递给另一个函数,也可以作为返回值。

    dart
    复制代码
    void printMessage(String Function(String) formatter, String message) {
      print(formatter(message));
    }
    
  • 返回类型: 虽然 Dart 允许省略返回类型,但为了代码的清晰性和可维护性,通常建议显式指定返回类型。

运算符 (Operators)

算术运算符

  • 常见运算符+-*/(除法返回 double), ~/(整除), %(取余)。

    dart
    复制代码
    int a = 5;
    int b = 2;
    print(a ~/ b); // 结果为 2
    print(a % b);  // 结果为 1
    

关系运算符

  • 比较运算符==!=><>=<=。这些运算符用于比较两个值,并返回 bool 类型。

    dart
    复制代码
    print(5 > 2); // true
    

逻辑运算符

  • 逻辑与 (&&) : 两个操作数都为真时,结果为真。

  • 逻辑或 (||) : 两个操作数中至少一个为真时,结果为真。

  • 逻辑非 (!) : 对布尔值取反。

    dart
    复制代码
    bool isAdult = age >= 18;
    if (isAdult && isStudent) {
      // do something
    }
    

位运算符

  • 按位运算&|^~(按位取反), <<(左移), >>(右移)。这些运算符操作的是二进制位。

    dart
    复制代码
    int x = 3; // 0011
    int y = 5; // 0101
    print(x & y); // 结果为 1 (0001)
    print(x | y); // 结果为 7 (0111)
    

赋值运算符

  • 赋值与复合赋值=+=-=*=/=%=,可以简化操作。

    dart
    复制代码
    int a = 10;
    a += 5; // a = 15
    
  • 空值赋值运算符 (??=) : 如果变量当前值为 null,则赋予新值。

    dart
    复制代码
    String? name;
    name ??= 'Guest'; // name 被赋值为 'Guest'
    

类型运算符

  • is: 检查对象是否为特定类型。

  • as: 将对象强制转换为特定类型。

  • is! : 检查对象是否不是特定类型。

    dart
    复制代码
    if (obj is String) {
      print(obj.length); // Dart 知道 obj 是 String 类型
    }
    

控制流 (Control Flow)

条件语句

  • if 语句: 标准的条件判断。

    dart
    复制代码
    if (age > 18) {
      print('Adult');
    } else if (age > 13) {
      print('Teenager');
    } else {
      print('Child');
    }
    

循环

  • for 循环: 标准的迭代语法。

    dart
    复制代码
    for (int i = 0; i < 5; i++) {
      print(i);
    }
    
  • for-in 循环: 用于遍历集合。

    dart
    复制代码
    List<String> names = ['Alice', 'Bob', 'Charlie'];
    for (var name in names) {
      print(name);
    }
    
  • while 循环: 在条件为真时执行循环体。

    dart
    复制代码
    int count = 0;
    while (count < 5) {
      print(count);
      count++;
    }
    
  • do-while 循环: 先执行一次循环体,然后检查条件。

    dart
    复制代码
    int count = 0;
    do {
      print(count);
      count++;
    } while (count < 5);
    

Switch 语句

  • switch-case: 用于多分支判断,支持整数、字符串和枚举类型。需要注意每个 case 分支后要使用 break,否则会继续执行后续分支。

    dart
    复制代码
    String command = 'OPEN';
    switch (command) {
      case 'OPEN':
        print('Opening');
        break;
      case 'CLOSE':
        print('Closing');
        break;
      default:
        print('Unknown command');
    }
    

异常 (Exceptions)

捕获与处理

  • try-catch: 用于捕获和处理异常。catch 可以捕获异常对象 (e) 和堆栈跟踪 (stackTrace)。

    dart
    复制代码
    try {
      var result = 5 ~/ 0;
    } catch (e, stackTrace) {
      print('Caught an exception: $e');
      print('Stack trace: $stackTrace');
    }
    
  • finally: 无论是否抛出异常,finally 块中的代码都会执行,通常用于资源释放或清理操作。

    dart
    复制代码
    try {
      var result = 5 ~/ 0;
    } catch (e) {
      print('Caught an exception: $e');
    } finally {
      print('This is always executed');
    }
    

自定义异常

  • 定义与抛出: Dart 允许你定义自定义异常类,实现 Exception 接口。

    dart
    复制代码
    class MyException implements Exception {
      final String message;
      MyException(this.message);
    
      @override
      String toString() => 'MyException: $message';
    }
    
    void test() {
      throw MyException('Something went wrong');
    }
    

类 (Classes)

基础知识

  • 定义类: Dart 是纯面向对象的语言,类是其基本构建块。类中可以包含字段、方法和构造函数。

    dart
    复制代码
    class Animal {
      String name;
      int age;
    
      Animal(this.name, this.age);
    
      void speak() {
        print('$name makes a noise.');
      }
    }
    
  • 构造函数: Dart 支持多种类型的构造函数,包括默认构造函数、命名构造函数、工厂构造函数。

    dart
    复制代码
    class Point {
      int x, y;
    
      // 默认构造函数
      Point(this.x, this.y);
    
      // 命名构造函数
      Point.origin() : x = 0, y = 0;
    }
    
    var p1 = Point(10, 20);
    var p2 = Point.origin();
    
  • 继承和多态: Dart 支持继承,使用 extends 关键字。子类可以覆盖父类的方法。

    dart
    复制代码
    class Dog extends Animal {
      Dog(String name, int age) : super(name, age);
    
      @override
      void speak() {
        print('$name barks.');
      }
    }
    
  • 抽象类和接口: Dart 中的抽象类使用 abstract 关键字,不能实例化。任何类都可以实现接口,即使它并不显式声明为接口。

    dart
    复制代码
    abstract class Shape {
      void draw();
    }
    
    class Circle implements Shape {
      @override
      void draw() {
        print('Drawing a circle');
      }
    }
    
  • 混入 (Mixins) : 使用 with 关键字可以实现类似多继承的功能,将一个类的功能混入另一个类。

    dart
    复制代码
    mixin Swimmer {
      void swim() {
        print('Swimming');
      }
    }
    
    class Fish with Swimmer {
      // Fish 现在具有 swim() 方法
    }
    

泛型 (Generics)

泛型类

  • 定义泛型类: 泛型用于提高代码的重用性和类型安全性。可以定义泛型类来处理不同类型的数据。

    dart
    复制代码
    class Box<T> {
      T value;
      Box(this.value);
    }
    
    var intBox = Box<int>(10);
    var strBox = Box<String>('Hello');
    

泛型方法

  • 定义泛型方法: 泛型不仅限于类,还可以应用于方法,允许方法处理多种类型的数据。

    dart
    复制代码
    T identity<T>(T value) {
      return value;
    }
    
    var result = identity<int>(42);
    

库和可见性 (Libraries and Visibility)

库与模块化

  • : Dart 的库是模块化的基础。每个 Dart 文件都是一个库。通过 import 指令导入库,使用 export 指令暴露库的部分或全部内容。

    dart
    复制代码
    import 'package:my_package/my_library.dart';
    export 'src/my_helper.dart'; // 重新导出
    
  • 可见性: 使用 _ 前缀标识库内私有成员(字段、方法或类)。这些成员只能在声明它们的库中访问。

    dart
    复制代码
    class MyClass {
      String _privateVar = 'private';
      void _privateMethod() {}
    }
    

异步支持 (Asynchronous Support)

异步编程

  • Future: Dart 中的 Future 表示一个异步操作的结果。使用 async 和 await 可以简化异步代码的书写,使其更接近同步代码的风格。

    dart
    复制代码
    Future<String> fetchData() async {
      return 'Data fetched';
    }
    
    void main() async {
      var data = await fetchData();
      print(data);
    }
    
  • StreamStream 是一个异步序列,用于处理一系列异步数据(如事件流)。

    dart
    复制代码
    Stream<int> countStream(int max) async* {
      for (int i = 1; i <= max; i++) {
        yield i;
      }
    }
    

生成器 (Generators)

迭代器生成

  • 同步生成器: 使用 sync* 关键字创建同步生成器,生成一个可以被迭代的对象。

    dart
    复制代码
    Iterable<int> getEvenNumbers(int n) sync* {
      for (int i = 0; i <= n; i += 2) {
        yield i;
      }
    }
    
  • 异步生成器: 使用 async* 生成异步流,产生异步数据。

    dart
    复制代码
    Stream<int> getAsyncEvenNumbers(int n) async* {
      for (int i = 0; i <= n; i += 2) {
        await Future.delayed(Duration(seconds: 1));
        yield i;
      }
    }
    

可被调用的类 (Callable Classes)

  • 实现 call 方法: 在 Dart 中,类可以实现 call 方法,从而使类的实例可以像函数一样调用。这在需要函数对象的地方非常有用。

    dart
    复制代码
    class Adder {
      int call(int a, int b) => a + b;
    }
    
    var adder = Adder();
    print(adder(2, 3)); // 输出 5
    

Isolate

  • 并发编程: Dart 中的并发模型基于 Isolate。每个 Isolate 拥有自己的内存空间,不与其他 Isolate 共享内存。Isolate 之间通过消息传递进行通信。

    dart
    复制代码
    import 'dart:isolate';
    
    void isolateEntry(SendPort sendPort) {
      sendPort.send('Hello from isolate');
    }
    
    void main() async {
      var receivePort = ReceivePort();
      await Isolate.spawn(isolateEntry, receivePort.sendPort);
    
      receivePort.listen((message) {
        print('Received: $message');
      });
    }
    

Typedefs

  • 类型别名: 使用 typedef 可以为函数类型或复杂的泛型类型定义一个简短的别名。这可以使代码更加简洁和易于维护。

    dart
    复制代码
    typedef IntBinaryOperation = int Function(int, int);
    
    int add(int a, int b) => a + b;
    IntBinaryOperation operation = add;
    

元数据 (Metadata)

元数据注解

  • 元数据: Dart 中的元数据以注解的形式存在,注解使用 @ 符号引导。常用的注解包括 @override@deprecated 等。

    dart
    复制代码
    class MyAnnotation {
      final String description;
      const MyAnnotation(this.description);
    }
    
    @MyAnnotation('This is a custom annotation')
    void myFunction() {
      print('Function with annotation');
    }
    
  • 内置元数据: Dart 提供了一些常见的内置元数据,如 @override 用于标记覆盖的父类方法,@deprecated 用于标记已弃用的功能。

    dart
    复制代码
    @deprecated
    void oldMethod() {
      print('This method is deprecated');
    }
    

    重要关键词 (Keywords)

this

  • this 关键字: 用于引用当前实例。通常用于区分实例变量和方法参数,或在构造函数中初始化实例变量。

    dart
    复制代码
    class MyClass {
      String name;
    
      MyClass(this.name);
    }
    

super

  • super 关键字: 用于调用父类的构造函数、方法或访问父类的属性。在子类中可以通过 super 关键字来调用父类中被重写的方法或构造函数。

    dart
    复制代码
    class Parent {
      void sayHello() {
        print('Hello from Parent');
      }
    }
    
    class Child extends Parent {
      @override
      void sayHello() {
        super.sayHello(); // 调用父类方法
        print('Hello from Child');
      }
    }
    

static

  • static 关键字: 用于定义类级别的成员。静态成员属于类,而不是类的实例,可以通过类名直接访问。

    dart
    复制代码
    class MyClass {
      static int counter = 0;
    
      static void increment() {
        counter++;
      }
    }
    
    void main() {
      MyClass.increment();
      print(MyClass.counter); // 输出 1
    }
    

new

  • new 关键字: Dart 使用 new 关键字来创建类的实例,尽管 Dart 允许省略这个关键字。

    dart
    复制代码
    var person = new Person('Alice', 30);
    

final

  • final 关键字: 用于定义运行时不可改变的变量。final 变量必须在运行时初始化,并且只能被赋值一次。

    dart
    复制代码
    final int number = 42;
    

const

  • const 关键字: 用于定义编译时常量。const 变量在编译时就必须赋值,并且不可更改。

    dart
    复制代码
    const double pi = 3.14159;
    

abstract

  • abstract 关键字: 用于定义抽象类。抽象类不能被实例化,通常包含抽象方法,子类必须实现这些方法。

    dart
    复制代码
    abstract class Shape {
      void draw();
    }
    

extends 和 implements

  • extends: 用于继承父类。子类继承父类的所有非私有成员。

    dart
    复制代码
    class Dog extends Animal {
      // Dog 类继承了 Animal 类的所有成员
    }
    
  • implements: 用于实现接口。类必须实现接口中所有的方法和属性。

    dart
    复制代码
    class Car implements Vehicle {
      @override
      void drive() {
        print('Driving');
      }
    }
    

enum

  • enum 关键字: 用于定义枚举类型。枚举类型表示有限的、固定数量的值集合。

    dart
    复制代码
    enum Color { red, green, blue }
    
    void main() {
      var favoriteColor = Color.blue;
      print(favoriteColor); // 输出 Color.blue
    }
    

assert

  • assert 关键字: 用于在开发过程中进行调试检查。assert 表达式为 true 时不做任何操作;如果为 false,则抛出异常。

    dart
    复制代码
    void main() {
      int age = 18;
      assert(age >= 18, 'Age must be 18 or older');
    }
    

总结

以上是 Dart 编程语言中的一些核心知识点的详细讲解,包括函数、运算符、控制流、异常处理、类、泛型、库和可见性、异步支持、生成器、可调用类、Isolate、typedefs、元数据、变量及重要的关键字。掌握这些知识点后,你将能够更好地理解和使用 Dart 进行开发。