跳转至

01-Dart 语法速通

基于 Vexfy 项目实战学习,适合有 Java 基础的程序员 30 分钟上手 Dart


1. Hello World

// Java
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

// Dart(更简洁)
void main() {
    print('Hello');
}

2. 变量和类型

// Dart 的 var 自动推断类型,等同于 Java 的 var
var name = "Luke";        // 自动推断 String
String name2 = "Luke";    // 显式类型也可以
int age = 34;
final double height = 183.0;  // final = Java 的 final
const PI = 3.14;              // const = 编译时常量,Java 没有

3. 空安全(Null Safety)

// Java:烦人的 NPE
String name = null;
name.length();  // NullPointerException!

// Dart:空安全,默认不可为 null,编译时就报错
String name = "Luke";
// name = null;  // ❌ 编译错误!

// 真的需要 null,加 ?
String? nullableName = null;  // 加 ? 表示可以为 null
nullableName?.length;          // 安全调用,null 就返回 null

Dart 从语言层面解决了 NPE,Java 14+ 的 Optional ,Dart 直接内置了。


4. 函数

// 单行箭头函数,等同于 Java 的 -> 表达式 lambda
int add(int a, int b) => a + b;

// 完整写法
int add(int a, int b) {
    return a + b;
}

// 可选命名参数(Java 没有这个)
void greet(String name, {String? title}) {
    print('$title $name');
}
greet('Luke');                  // title 为 null,不打印
greet('Luke', title: 'Mr.');    // Mr. Luke

5. 类和对象

// Java:需要手写 getter/setter
public class Song {
    private String title;
    public Song(String title) { this.title = title; }
    public String getTitle() { return title; }
}

// Dart:自动生成 getter/setter,直接访问属性
class Song {
    String title;       // 不用写 getter/setter
    String artist;

    Song(this.title, this.artist);  // 构造器简写
}

var song = Song('晴天', '周杰伦');
print(song.title);  // 直接访问,不用 getter
song.title = '七里香';  // 直接赋值,不用 setter

6. 继承

// Java
public class PlayerController extends BaseController {
    @Override
    public void play() {
        super.play();
    }
}

// Dart(语法几乎一样)
class PlayerController extends BaseController {
    @override  // Dart 用 @override 注解
    void play() {
        super.play();
    }
}

7. 接口和抽象

// Java
public interface PlayerService {
    void play();
    void pause();
}

// Dart(Dart 没有 interface 关键字,class 就是接口)
abstract class PlayerService {
    void play();  // 抽象方法
    void pause();
}

class PlayerImpl implements PlayerService {
    @override
    void play() { }
    @override
    void pause() { }
}

8. 集合(List / Map / Set)

// Java
List<String> list = Arrays.asList("a", "b", "c");
Map<String, Integer> map = new HashMap<>();
map.put("key", 1);

// Dart(更简洁直观)
var list = ['a', 'b', 'c'];   // List 字面量
var map = {'key': 1};           // Map 字面量
map['key'] = 1;               // 直接访问

// 遍历
for (var item in list) {
    print(item);
}

// 函数式(类似 Java Stream)
var doubled = list.map((e) => e * 2).toList();

9. 异步(Future + async / await)

// Java CompletableFuture
CompletableFuture<String> fetchData() {
    return CompletableFuture.supplyAsync(() -> "result");
}

// Dart(和 JavaScript 几乎一样,比 Java 简洁)
Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 1));
    return 'result';
}

// 调用
void main() async {
    var data = await fetchData();
    print(data);
}

10. 完整可运行示例代码

下面是包含上述所有特性的完整Dart代码示例,可以直接运行学习:

// Dart(最简形式)
// main函数添加async修饰,才能在内部使用await
void main() async {
  print('=' * 60);
  print('🚀 Dart基础语法示例运行开始');
  print('=' * 60);

  printHello();
  useVar();
  useNullSafety();
  useFunction();
  useClass();
  useInherit();
  useInterface();
  useCollection();
  await useAsync(); // await等待异步函数执行完成


  print('\n' + '=' * 60);
  print('✅ Dart基础语法示例运行结束');
  print('=' * 60);
}

//1. Hello World
void printHello() {
  print('\n📌 [1/9] Hello World 示例:');
  print('   输出内容: Hello');
}

//2. 变量和类型
void useVar() {
  print('\n📌 [2/9] 变量和类型 示例:');
  // Dart(很像,但有var和final)
  var name = "Luke"; // 自动推断 String
  print('   var自动推断类型 name:$name (类型: ${name.runtimeType})');
  String name2 = "Luke"; // 显式类型也可以
  print('   显式声明String类型 name2:$name2 (类型: ${name2.runtimeType})');
  int age = 34;
  print('   显式声明int类型 age:$age (类型: ${age.runtimeType})');
  final double height = 183.0; // Java的final,Dart也用final、
  print('   final修饰不可变变量 height:$height (类型: ${height.runtimeType})');
  const PI = 3.14; // 编译时常量,Java没有这个、
  print('   const编译时常量 PI:$PI (类型: ${PI.runtimeType})');
}

//3. 空安全(Null Safety)
void useNullSafety() {
  print('\n📌 [3/9] 空安全(Null Safety) 示例:');
  // Java(烦人的NPE)
  //String name = null; // 编译不报错,但运行时可能炸
  // name.length(); // NullPointerException!

  // Dart(空安全,默认不可为null)
  String name = "Luke";
  print('   默认不可为null变量 name = "$name",不可赋值为null');
  // name = null;  // ❌ 编译错误!安全

  // 如果真的需要null,加 ?
  String? nullableName = null; // 加?表示可以为null
  print('   可为null变量 nullableName = $nullableName');
  int? length = nullableName?.length; // 安全调用,null就返回null
  print('   安全调用nullableName?.length结果: $length');
}

//4. 函数
void useFunction() {
  print('\n📌 [4/9] 函数 示例:');
  // 函数(lambda)
  int add(int a, int b) => a + b;
  print('   Lambda函数 add(1, 2) = ${add(1, 2)}');

  // 函数(普通)
  int sub(int a, int b) {
    return a - b;
  }

  print('   普通函数 sub(1, 2) = ${sub(1, 2)}');

  // 可选参数
  int greet(String name, {int age = 0}) {
    return name.length + age;
  }

  print('   可选参数函数 greet("Luke") = ${greet("Luke")} (age默认值0)');
  print(
    '   可选参数函数 greet("Luke", age: 34) = ${greet("Luke", age: 34)} (age传值34)',
  );
}

//5. 类和对象
void useClass() {
  print('\n📌 [5/9] 类和对象 示例:');
  // Dart创建对象(不用new)
  var song = Song('晴天', '周杰伦');
  print('   Song实例 title: ${song.title} (类型: ${song.title.runtimeType})'); // 直接访问,不用getter/setter
  print('   Song实例 artist: ${song.artist} (类型: ${song.artist.runtimeType})');
}

// Dart(更简洁)
class Song {
  String title; // 不用写getter/setter,Flutter直接song.title访问
  String artist;
  Song(this.title, this.artist); // 构造器简写
}

//6. 继承
void useInherit() {
  print('\n📌 [6/9] 继承 示例:');
  // Dart创建对象(不用new)
  BaseController player = PlayerController();
  print('   父类引用指向子类实例 player.play() 输出:');
  player.play();

  PlayerController player2 = PlayerController();
  print('   子类实例 player2.play() 输出:');
  player2.play();
}

// Dart(更简洁)
class BaseController {
  void play() {
    print('     父类BaseController.play() 执行');
  }
}

class PlayerController extends BaseController {
  @override // Dart用@override注解,不是@Override
  void play() {
    print('     子类PlayerController.play() 调用super.play()前');
    super.play();
    print('     子类PlayerController.play() 调用super.play()后');
  }
}

//7. 接口和抽象类
void useInterface() {
  print('\n📌 [7/9] 接口和抽象类 示例:');
  // Dart创建对象(不用new)
  PlayerService player = PlayerImpl();
  print('   接口实现类实例 player.play() 输出:');
  player.play();
  print('   接口实现类实例 player.pause() 输出:');
  player.pause();
}

// Dart(Dart没有interface关键字,class就是接口)
// 用abstract class定义抽象类
abstract class PlayerService {
  void play(); // 抽象方法,不用abstract也行
  void pause();
}

class PlayerImpl implements PlayerService {
  @override
  void play() {
    print('     PlayerImpl.play() 执行: 播放');
  }

  @override
  void pause() {
    print('     PlayerImpl.pause() 执行: 暂停');
  }
}

//8. 集合(List/Map/Set)
void useCollection() {
  print('\n📌 [8/9] 集合(List/Map/Set) 示例:');
  // Java
  // List<String> list = Arrays.asList("a", "b", "c");
  // Map<String, int> map = new HashMap<>();
  // map.put("key", 1);
  // for (String item : list) { }

  // Dart(更简洁)
  var list = ['a', 'b', 'c']; // List字面量
  var map = {'key': 1}; // Map字面量
  map['key'] = 1; // 直接访问

  print('   List字面量 list: $list (类型: ${list.runtimeType})');
  print('   for-in遍历list结果:');
  // 遍历
  for (var item in list) {
    print('     $item');
  }

  print('   forEach遍历list结果:');
  // 函数式
  list.forEach((item) => print('     $item'));
  var doubled = list.map((e) => e * 2).toList();
  print('   函数式操作 list.map((e) => e * 2).toList() 结果: $doubled');
  print('   Map字面量 map: $map (类型: ${map.runtimeType})');
  print('   Map直接访问 map["key"] 结果: ${map['key']}');
}

//9. 异步(Future + async/await)
// 异步函数需要返回Future,返回值类型为Future<void>表示没有返回值
Future<void> useAsync() async {
  print('\n📌 [9/9] 异步(Future + async/await) 示例:');
  // Dart(和JavaScript很像)
  Future<String> fetchData(int requestId) async {
    await Future.delayed(Duration(seconds: 1));
    return '请求#$requestId 数据结果';
  }

  print('   开始调用异步函数fetchData(1),等待1秒...');
  var result = await fetchData(1);
  print('   异步函数返回结果: $result');
}

11. Dart 独有的好东西

11.1 级联操作符(..)

// Java 多行
song.setTitle('新歌');
song.setArtist('新歌手');
song.save();

// Dart 一行搞定,用 ..
song
    ..title = '新歌'
    ..artist = '新歌手'
    ..save();

10.2 字符串插值

var name = 'Luke';
print('Hello $name');        // Hello Luke
print('Age: ${age + 1}');   // Age: 35,支持表达式

10.3 ?? 操作符(null 合并)

var name = nullableName ?? '默认值';
// nullableName 为 null 时用默认值,等同于 Java 的 Optional.orElse()

10.4 命名构造器

class Song {
    String title;

    // 命名构造器 fromJson
    Song.fromJson(Map json) {
        title = json['title'];
    }
}

var song = Song.fromJson({'title': '晴天'});

11. 关键速查表

Dart Java 说明
var var 自动类型推断
final final 运行时常量
const static final 编译时常量
String? Optional<String> 可空类型
class A extends B class A extends B 继承
class A implements B class A implements B 实现
=> -> 箭头函数
$name %s + name 字符串插值
.. 级联调用 obj.method1().method2() 级联操作符
async / await CompletableFuture 异步
{String? title} 命名可选参数

12. 结合 Vexfy 项目看真实代码

12.1 Song 模型(Dart 类)

// 文件:app/lib/data/models/song_model.dart
class Song {
    String id;         // 歌曲唯一ID(MD5)
    String title;      // 歌名
    String artist;     // 歌手
    String album;       // 专辑
    String path;        // 文件路径
    int duration;       // 时长(毫秒)

    Song({
        required this.id,
        required this.title,
        required this.artist,
        required this.album,
        required this.path,
        required this.duration,
    });

    // 命名构造器:从数据库 Map 构建
    Song.fromMap(Map<String, dynamic> map)
        : id = map['id'],
          title = map['title'],
          artist = map['artist'],
          album = map['album'],
          path = map['path'],
          duration = map['duration'];

    // 转为 Map:存入数据库
    Map<String, dynamic> toMap() => {
        'id': id,
        'title': title,
        'artist': artist,
        'album': album,
        'path': path,
        'duration': duration,
    };
}

对比 Java: 不需要手写 getter/setter,Dart 自动生成。

12.2 GetX Controller(Dart 类 + 状态管理)

// 文件:app/lib/services/player_service.dart
class PlayerService extends GetxController {
    // RxInt = GetX 的响应式变量,类似 Java 的 AtomicInteger
    final currentIndex = 0.obs;
    final isPlaying = false.obs;
    final playlist = <Song>[].obs;

    // 播放
    void play() {
        isPlaying.value = true;
    }

    // 暂停
    void pause() {
        isPlaying.value = false;
    }

    // 切下一首
    void next() {
        if (currentIndex.value < playlist.length - 1) {
            currentIndex.value++;
        }
    }
}

对比 Java: .obs 让变量变成响应式的,值变化时 UI 自动更新(类似 Spring 的事件监听,但更简洁)。


下一步