目录

一、函数(Flutter 组件开发基础)

1. 函数的定义与调用

2. Dart 特色函数

(1)匿名函数

(2)箭头函数

(3)参数类型:必选参数 / 可选参数

二、集合类型

1. List(列表,等价于其他语言的数组)

2. Map(键值对)

3. Set(无重复集合)

三、面向对象

1. 类与对象

2. 继承(extends)

四、flutter实战

结尾


一、函数(Flutter 组件开发基础)

        函数是封装可复用代码的最小单元,Flutter 中自定义组件、处理逻辑都离不开函数。

1. 函数的定义与调用

// 函数格式:返回值类型 函数名(参数类型 参数名) { 函数体 }
// 示例:定义一个计算两数之和的函数
int add(int num1, int num2) {
  int result = num1 + num2;
  return result; // 返回计算结果
}

// 无返回值函数,这里没有写返回类型,编译器会推成dynamic类型
printInfo(String name) {
  print("姓名:$name");
}

void main() {
  // 调用函数:函数名(参数值)
  int sum = add(5, 3);

  print("和为:$sum"); // 输出:和为:8
  
  printInfo("李四"); // 输出:姓名:李四
}

注:省略返回值类型,Dart 会自动推断,但推荐显式声明,代码更清晰。

2. Dart 特色函数

(1)匿名函数

        匿名函数就是 “没有名字的函数”,它的核心作用是 “临时用一次”,不用单独定义函数名,尤其适合作为参数传递给其他函数(比如集合的遍历、按钮的点击回调)。

void main() {
  List<int> nums = [1,2,3,4];
  
  // 匿名函数作为forEach的参数
  nums.forEach((int num) {
    print("数字:$num,平方:${num*num}");
  });
  
  // 省略参数类型,Dart自动推断
  nums.forEach((num) {
    print("数字:$num,立方:${num*num*num}");
  });
}

(2)箭头函数

        当函数体只有一行代码时,可用箭头函数 => 简化。

void main() {
  // 普通函数
  int multiply(int a, int b) {
    return a * b;
  }
  
  // 箭头函数(等价于上面的函数)
  int multiply2(int a, int b) => a * b;
  
  print(multiply2(4,5)); // 输出:20
  
  // Flutter实战场景:构建Text组件的箭头函数
  Widget getTextWidget(String content) => Text(
    content,
    style: TextStyle(fontSize: 16),
  );
}

注意:箭头函数后只能跟一行代码,不能加 {},也不能加 return,会自动隐含。

(3)参数类型:必选参数 / 可选参数

       Flutter 中所有组件的参数都是 “可选命名参数”,比如 Text("文本", style: TextStyle()),这是 Dart 函数参数的核心设计,所以这个必须掌握。

参数类型 语法 示例 Flutter 应用
必选参数 直接写参数 add(int a, int b) 函数必须传的核心参数
可选位置参数 [] 包裹 sayHello(String name, [int? age]) 非核心参数,按位置传
可选命名参数 {} 包裹 sayHi({String? name, int? age}) 所有 Flutter 组件参数
// 1. 可选位置参数(按位置传参,可省略)
String sayHello(String name, [int? age]) {
  if (age == null) {
    return "你好,$name!";
  } else {
    return "你好,$name!年龄:$age";
  }
}

// 2. 可选命名参数(按名称传参,顺序无关)
String sayHi({String? name, int? age}) {
  return "Hi~ ${name ?? '匿名用户'} ${age != null ? '(' + age.toString() + '岁)' : ''}";
}

// 3. required关键字(强制传命名参数)
String sayGoodbye({required String name}) {
  return "再见,$name!";
}

void main() {
  
  print(sayHello("小明")); // 输出:你好,小明!
  print(sayHello("小红", 18)); // 输出:你好,小红!年龄:18
  
  
  print(sayHi(name: "小李")); // 输出:Hi~ 小李 
  print(sayHi(age: 20, name: "小王")); // 输出:Hi~ 小王 (20岁)
  
  
  print(sayGoodbye(name: "小张")); // 必须传name,否则报错
  // print(sayGoodbye()); // 报错:缺少required参数name
}

        Flutter 写 Text 组件时,"Hello Flutter"必选位置参数(必须传,否则不知道显示什么),而 style:textAlign:可选命名参数(可传可不传,不传就用默认样式);required 关键字则用于 “自定义 Widget 时,强制调用者传某个参数”,比如你写一个 “用户卡片 Widget”,必须传用户姓名,就可以用 required String name

Text(
  "Hello Flutter", // 必选参数(第一个位置参数) 
  style: TextStyle(fontSize: 20), // 可选命名参数 
  textAlign: TextAlign.center, // 可选命名参数
);

二、集合类型

        Dart 有三种核心集合:List(列表)、Map(键值对)、Set(无重复集合)

1. List(列表,等价于其他语言的数组)

        List 是有序、可重复的集合,最大特点是 “通过索引取值”(比如 fruits[0] 取第一个元素),这也是 Flutter 中 ListViewGridView 渲染列表的核心数据来源——你后端接口返回的 “商品列表”,本质就是一个 List,每个元素是一个商品的信息(Map 类型)。

void main() {
  // 1. 声明List
  // 方式1:指定类型,避免存错数据类型
  List<String> fruits = ["苹果", "香蕉", "橙子"];
  // 方式2:空List,之后动态添加数据
  List<int> nums = [];
  
  // 2. 常用操作
  fruits.add("葡萄"); // 添加元素:["苹果","香蕉","橙子","葡萄"]
  fruits.insert(1, "草莓"); // 插入元素:["苹果","草莓","香蕉","橙子","葡萄"]
  fruits.remove("香蕉"); // 删除元素:["苹果","草莓","橙子","葡萄"]
  print(fruits[0]); // 取值:苹果
  print(fruits.length); // 长度:4
  
  // 3. 遍历+转换(Flutter中最核心的用法)
  // 将List<String>转为List<Widget>
    List<Widget> fruitWidgets = fruits.map((fruit) {
        // 对遍历到的每一个 fruit(单个水果名称),返回一个 Text 组件
        return Text(fruit);
  }).toList();// 4. 把 map 生成的迭代器转换成真正的 List 列表(关键!map 本身不是列表)

  print(fruitWidgets); // 输出:[Text("苹果"), Text("草莓"), ...]
}

注:

  • add /   insert /   remove 是 “修改 List” 的基础操作,对应 Flutter 中 “下拉加载更多”(add)、“插入新数据”(insert)、“删除列表项”(remove)的业务场景;
  • map() 是 Flutter 中 “数据转 Widget” 的核心方法 —— 后端返回的是 “数据 List”,你需要把每个数据转换成一个 Widget(比如 Text、Container),再用 toList() 转成 Widget List,才能给 ListView 渲染。

2. Map(键值对)

        Map 是无序、键唯一的键值对集合,核心特点是 “通过键取值”(比如 user["name"]),这是解析后端 JSON 数据的 “标配”—— 后端返回的几乎所有 JSON 数据,在 Dart 中都会被解析成 Map 类型(比如 {"name":"张三","age":25})。

void main() {
  // 1. 声明Map(键,值)
  Map<String, dynamic> user = {
    "name": "张三",
    "age": 25,
    "isVip": true,
    "hobbies": ["打球", "编程"]
  };
  
  // 2. 常用操作
  print(user["name"]); // 取值:张三
  user["age"] = 26; // 修改值
  user["address"] = "北京"; // 添加新键值对
  user.remove("isVip"); // 删除键值对
  
  // 3. 遍历Map
  user.forEach((key, value) {
    print("$key:$value");
  });
  
}

注:Map 的键(key)必须是唯一的,比如不能同时有两个 "name" 键。

3. Set(无重复集合)

        Set 是无序、元素唯一的集合,核心作用是 “去重”,比如你有一个 “用户标签 List”,里面有重复的标签,用 Set 转换一下就能自动去重,适合 “筛选不重复数据” 的场景。

void main() {
  Set<int> nums = {1,2,2,3,3,3};
  print(nums); // 自动去重:{1,2,3}
  
  nums.add(4); // 添加元素
  nums.add(2); // 重复元素,不生效
  print(nums); // {1,2,3,4}
}

三、面向对象

        Dart 是纯面向对象语言,所有东西都是对象(包括数字、函数),而 Flutter 中所有 Widget(比如 Text、Container)都是 “类的实例”,自定义 Widget 本质就是 “定义一个类,继承StatelessWidget 或者 StatefulWidget”,所以我们必须理解 “类、对象、继承” 。

1. 类与对象

        类是 “模板”,对象是 “根据模板创建的具体实例”—— 比如 Person 类是 “人的模板”,包含姓名、年龄等属性,以及打招呼的方法;p1 是 “张三这个具体的人”,是 Person 类的一个对象。

//格式
class 类名{

    成员变量

    成员函数
}
// 定义类:类名首字母大写(大驼峰规则,Flutter所有Widget都遵循)
class Person {
  // 类的属性(成员变量):对应“人的特征”
  String name;
  int age;
  
  // 构造函数:创建对象时初始化属性,这是简化的写法
  Person(this.name, this.age);
  
  // 类的方法(成员函数):对应“人的行为”
  void sayHello() {
    print("我是$name,今年$age岁!");
  }
  
  // 带返回值的方法:返回“人的信息字符串”
  String getInfo() {
    return "姓名:$name,年龄:$age";
  }
}

void main() {
  // 创建对象:类名(参数) → 根据模板创建具体实例
  Person p1 = Person("张三", 25);
  // 调用方法:对象.方法名()
  p1.sayHello(); // 输出:我是张三,今年25岁!
  print(p1.getInfo()); // 输出:姓名:张三,年龄:25
  
  // 访问属性:对象.属性名
  print(p1.name); // 输出:张三
  p1.age = 26; // 修改属性
  p1.sayHello(); // 输出:我是张三,今年26岁!
}

2. 继承(extends)

        继承是 “子类可以直接用父类的属性和方法”,还可以新增自己的属性 / 方法,或重写父类的方法。Flutter 中所有 Widget 都继承自 Widget 类。

        关键字:extends

        使用super可以调用父类的内容

// 父类:Person(基础模板)
class Person {
  String name;
  int age;
  
  Person(this.name, this.age);
  
  void sayHello() {
    print("我是$name,今年$age岁!");
  }
}

// 子类:Student(继承Person,新增“班级”属性)
class Student extends Person {
  // 子类新增属性:学生特有的“班级”
  String className;
  
  // 子类构造函数:super调用父类构造函数(必须)
  Student(String name, int age, this.className) : super(name, age);
  
  // 重写父类方法:@override注解(可选,但推荐加,代码更清晰)
  @override
  void sayHello() {
    // 调用父类方法(可选,保留父类逻辑)
    super.sayHello();
    // 新增子类逻辑:学生特有的打招呼内容
    print("我是$className的学生!");
  }
  
  // 子类新增方法:学生特有的“学习”行为
  void study() {
    print("$name在$className学习!");
  }
}

void main() {
  Student s = Student("小红", 18, "三年二班");
  s.sayHello(); 
  // 输出:
  // 我是小红,今年18岁!(父类方法)
  // 我是三年二班的学生!(子类新增逻辑)
  s.study(); // 输出:小红在三年二班学习!(子类新增方法)
}
  • 类的构造函数参数的简化写法必须用 this.属性名,比如 Person(this.name, this.age),否则属性不会被初始化。
  • 如果父类的构造函数需要传入参数,则继承时必须用 super 调用父类构造函数并传参;子类构造函数的函数体第一句必须写 : super(父类参数),比如 Student(name, age, className) : super(name, age)

四、flutter实战

        现在看不懂具体每行代码干什么没关系,下面会讲一下大致流程,能明白大致流程就行。

        将下面的代码复制粘贴到main.dart文件中,保存一下,然后使用鸿蒙模拟器运行即可。

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dart 核心语法实战',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const StudentManagerPage(),
    );
  }
}

// 页面组件:学生信息管理页
class StudentManagerPage extends StatefulWidget {
  const StudentManagerPage({super.key});

  @override
  State<StudentManagerPage> createState() => _StudentManagerPageState();
}

class _StudentManagerPageState extends State<StudentManagerPage> {
  // 1. 集合知识点:List(存储学生列表)、Set(存储去重标签)、Map(存储示例用户)
  final List<Student> _studentList = [];
  final Set<String> _tagSet = {"学生", "在校", "青年"}; // 初始标签(Set自动去重)
  final Map<String, dynamic> _demoUser = {
    // Map:模拟接口返回的用户数据
    "name": "默认学生",
    "age": 18,
    "className": "高一(1)班",
    "tags": ["学习", "运动", "阅读"]
  };

  /// 构建用户信息字符串
  /// [name]:必填,[age]:可选,[className]:可选
  String buildUserInfo({
    required String name,
    int? age,
    String? className,
  }) {
    // 空安全处理
    String ageStr = age?.toString() ?? "未知";
    String classStr = className ?? "未分班";
    return "姓名:$name,年龄:$ageStr,班级:$classStr";
  }

  // 3. 函数知识点:箭头函数
  /// 生成默认学生(箭头函数,返回Student对象)
  Student _generateDefaultStudent() => Student(
        _demoUser["name"],
        _demoUser["age"],
        _demoUser["className"],
      );

  // 4. 业务方法:添加学生
  void _addStudent() {
    setState(() {
      final newStudent = _generateDefaultStudent();
      _studentList.add(newStudent);
      // Set去重:添加重复标签不会生效
      _tagSet.addAll(_demoUser["tags"]);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("学生信息管理")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 按钮:添加学生
            ElevatedButton(
              onPressed: () {
                // 匿名函数:按钮点击事件
                _addStudent();
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text("添加学生成功!")),
                );
              },
              child: const Text("添加默认学生"),
            ),
            const SizedBox(height: 20),
            // 展示去重标签(Set转List,map转换为Widget)
            const Text("学生标签(Set去重):"),
            Wrap(
              spacing: 8,
              children: _tagSet.map((tag) {
                // List.map转换Widget(核心知识点)
                return Chip(label: Text(tag));
              }).toList(), // 必须加toList()!
            ),
            const SizedBox(height: 20),
            const Text("学生列表:"),
            Expanded(
              child: _studentList.isEmpty
                  ? const Center(child: Text("暂无学生,点击添加"))
                  : ListView.builder(
                      itemCount: _studentList.length,
                      itemBuilder: (context, index) {
                        final student = _studentList[index];
                        // 调用可选参数函数:构建学生信息
                        final studentInfo = buildUserInfo(
                          name: student.name,
                          age: student.age,
                          className: student.className,
                        );
                        return ListTile(
                          title: Text(studentInfo),
                          subtitle: Text(student.sayHello()), // 调用类的方法
                          trailing: IconButton(
                            icon: const Icon(Icons.delete),
                            onPressed: () {
                              // 匿名函数:删除学生
                              setState(
                                  () => _studentList.removeAt(index)); // 箭头函数简化
                            },
                          ),
                        );
                      },
                    ),
            ),
          ],
        ),
      ),
    );
  }
}

// 面向对象:父类Person
class Person {
  String name;
  int age;

  // 构造函数(Dart简化写法:this.属性)
  Person(this.name, this.age);

  // 类的方法
  String sayHello() {
    return "我是$name,今年$age岁";
  }
}

// 面向对象:子类Student(继承Person)
class Student extends Person {
  String className;

  // 子类构造函数:super调用父类构造(必须)
  Student(String name, int age, this.className) : super(name, age);

  // 重写父类方法
  @override
  String sayHello() {
    // 调用父类方法 + 子类扩展逻辑
    return "${super.sayHello()},就读于$className";
  }

  // 子类新增方法
  void study() {
    print("$name在$className学习!");
  }
}

整个代码大致可分为三部分:

1. 通过方法操作数据

2. 构建页面

3. 类

我们跟着运行的界面一步步来看

这个界面,因为学生列表为空,使用显示,暂无学生,标签显示的也是标签列表中默认的内容。

然后我们点击页面中的“添加默认学生”按钮

第一步:他会执行点击事件,点击事件是一个匿名函数,函数中干了两件事:1. 添加学生,2. 显示消息。

第二步:执行添加学生的函数,里面通过_generateDefaultStudent()函数,将Map里面的内容创建成一个学生类对象。添加到学生列表,并将对应的标签添加到标签列表。

第三步:显示一个提示消息,内容是“添加学生成功”。

第四步:将现在标签列表中的标签显示出来。

第五步:先获取学生列表的当前元素,buildUserInfo函数返回一个字符串,把他作为标题。然后输入学生类里面的sayHello方法,显示出来。

第六步:创建一个删除按钮,点击时通过箭头函数将当前元素从列表中移除。

结尾

        这个程序中用到很多知识,包括函数、集合、类,大家可以好好看一下这个案例,了解一下它的执行流程。通过这个案例,我们系统地落地了 Dart 语言的核心语法特性,从基础的集合操作(List/Set/Map)、函数用法(可选参数、箭头函数、匿名函数),到面向对象编程(类的继承、方法重写),再到空安全处理等现代 Dart 特性,都在实际的 Flutter 界面开发中得到了体现。

        组件的使用看不懂没关系,之后还会学,这个案例的价值不仅在于语法的实践,更在于展示了如何将 Dart 语言特性与 Flutter 组件开发结合。

        编程的本质是解决问题,而语法只是工具。希望这个小案例能帮助你打通「语法学习」到「实战应用」的链路,在后续的 Flutter 开发之路上,始终以解决实际业务问题为导向,让每一个语法知识点都能发挥其真正的价值。

        欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐