Skip to content
大纲

2. 语法概览

https://dart.cn/guides/language/language-tour

2.1 Hello, World

dart
// 每个 App 都有个 main() 函数
void main(List<String> args) {
  print('Hello, World');
}

2.2 变量定义

不需要显式的生命类型

dart
void main(List<String> args) {
  // string
  var name = 'Voyager I';
  // int
  var year = 1977;
  // float
  var antennaDiameter = 3.7;
  // array
  var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];

  // object
  var image = {
    'tags': ['saturn'],
    'url': '//path/to/saturn.jpg'
  };
  print(name);
  print(year);
  print(antennaDiameter);
  print(flybyObjects);
  print(image);
}

2.2.1 变量的定义

除了 null 之外, 所有的类型都是对象, 以下是建议的定义方式

dart
var name = 'duoli';

2.2.2 空安全

定义空的变量(未启用空安全)

dart
int? lineNumber;

// assert 在生产环境会被忽略, 开发过程中如果数据不符会抛出异常
assert(lineCount == null);

启用空安全之后所有的变量必须设置初始值

dart
int lineNumber = 1;

2.2.3 延迟初始化变量

延迟初始化变量使用 late 修饰符

  • 声明非空但不在声明时候初始化(例如有一些耗费资源的操作)
  • 延迟初始化
late String description;

2.2.4 final 和 const

定义之后均不可更改 final 可以用在实例变量(类属性)中, const 则不可以

dart
class Point{
    final x;
    
    // 创建常量值
    final bar = const 3.14;
    final foo = const [];
}
dart
const bar = 10000;
const foo = bar * 3.14;

// 可以被更改
var foo = const 3.14;

[WIP] 如果使用 const 修饰类中的变量,则必须加上 static 关键字,即 static const

流程控制

dart
for (final object in flybyObjects) {
  print(object);
}

函数

标准函数

dart
int fibonacci(int n) {
  if (n == 0 || n == 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

箭头函数, Java 中是瘦箭头(->)

flybyObjects.where((name) => name.contains('turn')).forEach(print);

注释

dart
// 单行注释

/// 文档注释

/*
 多行注释
 */

导入

dart
import 'dart:math';

import 'package:test/test.dart'

import 'path/to/my_other_file.dart'

dart
class Spacecraft {
  String name;
  DateTime? launchDate;

  // 只读非 final 属性
  int? get launchYear => launchDate?.year;

  // 携带语法糖的构造器
  Spacecraft(this.name, this.launchDate) {
    // Initialization code goes here.
  }

  // 指向默认的命名构造器
  Spacecraft.unlaunched(String name) : this(name, null);

  // 方法
  void describe() {
    print('Spacecraft: $name');
    // Type promotion doesn't work on getters.
    var launchDate = this.launchDate;
    if (launchDate != null) {
      int years = DateTime.now().difference(launchDate).inDays ~/ 365;
      print('Launched: $launchYear ($years years ago)');
    } else {
      print('Unlaunched');
    }
  }
}

枚举

dart
enum PlanetType { terrestrial, gas, ice }

增强型枚举

dart
/// 枚举太阳系中的行星和他们的属性
enum Planet {
  mercury(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  venus(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  // ···
  uranus(planetType: PlanetType.ice, moons: 27, hasRings: true),
  neptune(planetType: PlanetType.ice, moons: 14, hasRings: true);

  /// 实例生成器
  const Planet(
      {required this.planetType, required this.moons, required this.hasRings});

  /// 所有实例变量都是 final 类型
  final PlanetType planetType;
  final int moons;
  final bool hasRings;

  /// 增强型的 Getter
  bool get isGiant =>
      planetType == PlanetType.gas || planetType == PlanetType.ice;
}

增强型枚举的引用

dart
final yourPlanet = Planet.earth;

if (!yourPlanet.isGiant) {
  print('Your planet is not a "giant planet".');
}

继承(扩展类)

dart
class Orbiter extends Spacecraft {
  double altitude;

  Orbiter(super.name, DateTime super.launchDate, this.altitude);
}

Mixins

类似于 php 中的 trait

dart
mixin Piloted {
  int astronauts = 1;

  void describeCrew() {
    print('Number of astronauts: $astronauts');
  }
}

使用的时候写在类定义的一行中, 使用 with

dart
class PilotedCraft extends Spacecraft with Piloted {
  // ···
}

接口和抽象类

Dart 没有 interface 关键字, 所有的类都可以是 interface 被实现, dart 中成为这种实现方式是隐式接口

dart
class MockSpaceship implements Spacecraft {
  // ···
}

为了把类和其他类做区别, 可以创建抽象类, 抽象类中可以包含抽象方法

dart
abstract class Describable {
  void describe();

  void describeWithEmphasis() {
    print('=========');
    describe();
    print('=========');
  }
}

异步

使用 asyncawait 可以避免回调地狱, 并使代码具有可读性

dart
const oneSecond = Duration(seconds: 1);
// ···
Future<void> printWithDelay(String message) async {
  await Future.delayed(oneSecond);
  print(message);
}

这个示例可以让代码看起来比较清爽, 如果不知道不清爽的代码, 也就不必知道了

dart
Future<void> createDescriptions(Iterable<String> objects) async {
  for (final object in objects) {
    try {
      var file = File('$object.txt');
      if (await file.exists()) {
        var modified = await file.lastModified();
        print(
            'File for $object already exists. It was modified on $modified.');
        continue;
      }
      await file.create();
      await file.writeAsString('Start describing $object in this file.');
    } on IOException catch (e) {
      print('Cannot create description for $object: $e');
    }
  }
}

使用 async* 关键字, 可以为你提供一个可读性更好的方式去生成 Stream

Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {
  for (final object in objects) {
    await Future.delayed(oneSecond);
    yield '${craft.name} flies by $object';
  }
}

异常

使用 throw 关键字抛出一个异常

dart
if (astronauts == 0) {
  throw StateError('No astronauts.');
}
dart
Future<void> describeFlybyObjects(List<String> flybyObjects) async {
  try {
    for (final object in flybyObjects) {
      var description = await File('$object.txt').readAsString();
      print(description);
    }
  } on IOException catch (e) {
    print('Could not describe object: $e');
  } finally {
    flybyObjects.clear();
  }
}