第一个 Dart 程序
学习一门编程语言,最好的方式不是先背语法规则,而是先跑起来一个程序,再一行一行地问这是什么意思。
本章我们将从一个最简单的程序出发,逐步扩展到一个稍微完整的小程序,在这个过程中把 Dart 最基础的概念都过一遍。
最简单的程序:Hello, Dart!
打开 DartPad(或本地编辑器),输入以下代码:
实例
print('Hello, Dart!');
}
点击运行,输出:
Hello, Dart!
就这 3 行代码。现在我们来把每一个字符都弄清楚。
逐行解析
void main() {
这是程序的入口函数声明,Dart 程序永远从 main() 开始执行。
拆开来看:
| 部分 | 含义 |
|---|---|
| void | 返回值类型。void 表示"这个函数执行完后不返回任何值" |
| main | 函数名。这是 Dart 约定的入口函数名,不能改成别的 |
| () | 参数列表。这里是空的,表示 main 函数不接受任何参数 |
| { | 函数体的开始。与最后一行的 } 配对,包裹函数的所有代码 |
main() 是 Dart 的唯一入口。不管你的程序有多少个文件、多少个类,执行总是从 main() 的第一行开始。
print('Hello, Dart!');
这是一条语句,作用是把括号内的内容输出到控制台。
拆开来看:
| 部分 | 含义 |
|---|---|
| 内置函数名,用于向控制台输出一行文字 | |
| (...) | 函数调用的参数列表 |
| 'Hello, Dart!' | 一个字符串字面量,用单引号 ' 包裹 |
| ; | 语句结束符。每条语句必须以分号结尾 |
| 前面的两个空格 | 缩进,表示这行代码属于 main() 函数内部。Dart 约定用 2 个空格缩进 |
}
main() 函数体的结束标志,与开头的 { 配对。
整体结构图
void main() { ← 函数签名(返回类型 + 函数名 + 参数)
print('Hello, ← 函数体:调用 print 函数
Dart!'); ← 传入字符串参数,以 ; 结尾
} ← 函数体结束
字符串的两种写法
Dart 中字符串可以用单引号或双引号包裹,两者完全等价。
实例
print('Hello, Dart!'); // 单引号
print("Hello, Dart!"); // 双引号,效果相同
}
Hello, Dart! Hello, Dart!
什么时候用哪种引号?可以参考以下场景:
| 场景 | 推荐 | 示例 |
|---|---|---|
| 一般情况 | 单引号(Dart 社区约定) | 'Hello' |
| 字符串内含有单引号 | 双引号 | "It's a beautiful day!" |
| 字符串内含有双引号 | 单引号 | '他说:"你好"' |
字符串内容本身含有单引号时,用双引号包裹更方便,省去转义。Dart 社区约定优先使用单引号,本教程后续也以单引号为主。
注释
注释是写给人看的说明文字,Dart 编译器会完全忽略它。
实例
// 这是单行注释,从 // 开始到行尾
print('Hello, Dart!'); // 也可以写在语句后面
/*
这是多行注释。
可以跨越多行,
常用于临时注释掉一大段代码。
*/
/// 这是文档注释,用于描述函数、类或变量的作用。
/// IDE 会将文档注释显示为悬浮提示。
}
| 注释类型 | 语法 | 用途 |
|---|---|---|
| 单行注释 | // 内容 | 解释某一行代码 |
| 多行注释 | /* 内容 */ | 注释掉一段代码,或写较长说明 |
| 文档注释 | /// 内容 | 描述 API,生成文档用 |
好注释解释"为什么",而不是"做了什么"。代码本身已经说明了"做了什么",注释应该补充背后的原因或意图。
变量:给数据起名字
程序不可能只输出固定文字,我们需要变量来存储和使用数据。
实例
String name = 'RUNOOB';
int age = 25;
double height = 1.68;
bool isStudent = true;
print(name);
print(age);
print(height);
print(isStudent);
}
RUNOOB 25 1.68 true
变量声明的格式
类型名 变量名 = 初始值 ; │ │ │ └─ 语句结束符 │ │ └─ 赋值运算符 │ └─ 你给这个数据起的名字 └─ 告诉 Dart 这个变量存储什么类型的数据
基本数据类型速览
| 类型 | 说明 | 示例 |
|---|---|---|
| String | 文本字符串 | 'RUNOOB'、"hello" |
| int | 整数 | 25、-10、0 |
| double | 小数(浮点数) | 1.68、3.14 |
| bool | 布尔值(真/假) | true、false |
数据类型的详细内容将在后续章节展开,这里先有个初步印象。
用 var 自动推断类型
每次都写类型名有点繁琐。
Dart 支持用 var 关键字自动推断变量类型——编译器会根据你赋的值来判断类型。
实例
var name = 'RUNOOB'; // 推断为 String
var age = 25; // 推断为 int
var height = 1.68; // 推断为 double
var isStudent = true; // 推断为 bool
print(name);
print(age);
}
RUNOOB 25
var 推断的类型在编译期就确定了,之后不能再赋值成别的类型。
实例
var name = 'RUNOOB';
name = 'Bob'; // 可以,仍然是 String
// name = 123; // 错误:不能把 int 赋给 String 类型的变量
}
什么时候用 var,什么时候写明类型?
| 场景 | 推荐 | 原因 |
|---|---|---|
| 局部变量,类型一眼就能看出来 | var | 更简洁 |
| 函数参数、类的字段、返回值类型 | 写明类型 | 代码更清晰,自文档化 |
字符串插值:把变量嵌入字符串
如果想把变量的值嵌入到字符串里,Dart 提供了非常简洁的字符串插值语法——用 $变量名 或 ${表达式}。
实例
var name = 'RUNOOB';
var age = 25;
print('我叫 $name,今年 $age 岁。');
print('明年我将 ${age + 1} 岁。');
}
我叫 RUNOOB,今年 25 岁。 明年我将 26 岁。
| 语法 | 用途 | 示例 |
|---|---|---|
| $变量名 | 直接嵌入变量值,简洁 | $name |
| ${表达式} | 嵌入任意表达式(计算、方法调用等) | ${age + 1}、${name.toUpperCase()} |
相比 print('我叫 ' + name + ',今年 ' + age.toString() + ' 岁。') 这种字符串拼接写法,插值语法更清晰、更安全,是 Dart 的惯用风格。
一个稍完整的小程序
现在我们把前面学到的东西综合起来,写一个稍微真实一点的程序:一个简单的自我介绍生成器。
实例
// 个人信息
var name = 'RUNOOB';
var age = 25;
var city = '上海';
var isStudent = false;
var hobby = 'Dart 编程';
// 生成介绍语:三元运算符判断身份
var occupation = isStudent ? '学生' : '职场人';
print('=============================');
print(' 个人简介');
print('=============================');
print('姓名:$name');
print('年龄:$age 岁');
print('城市:$city');
print('身份:$occupation');
print('爱好:$hobby');
print('-----------------------------');
print('大家好,我是来自$city的$name,');
print('今年 $age 岁,是一名$occupation。');
print('我的爱好是${hobby},很高兴认识大家!');
print('=============================');
}
=============================
个人简介
=============================
姓名:RUNOOB
年龄:25 岁
城市:上海
身份:职场人
爱好:Dart 编程
-----------------------------
大家好,我是来自上海的RUNOOB,
今年 25 岁,是一名职场人。
我的爱好是Dart 编程,很高兴认识大家!
=============================
新出现的语法:三元运算符
实例
这是 Dart 的三元运算符,格式为:
条件 ? 条件为真时的值 : 条件为假时的值
等价于以下 if/else 写法:
实例
if (isStudent) {
occupation = '学生';
} else {
occupation = '职场人';
}
三元运算符在值只有两种可能时非常简洁,后续章节会详细介绍 if/else 的完整用法。
代码风格:Dart 的书写规范
好的代码风格让代码更易读、更专业。
Dart 有一套官方推荐的规范,初学阶段掌握以下几点就够了。
缩进用 2 个空格
实例
void main() {
print('Hello');
}
// 不推荐:4 个空格(其他语言常见,但 Dart 社区偏好 2 格)
变量和函数名用小驼峰(lowerCamelCase)
实例
// var first_name = 'RUNOOB'; // 下划线风格:非 Dart 惯例
// var FirstName = 'RUNOOB'; // 大驼峰:保留给类名
类名用大驼峰(UpperCamelCase)
实例
// class user_profile { } // 错误
// class userProfile { } // 错误
常量用小驼峰(不是全大写)
实例
// const MAX_RETRIES = 3; // 这是 C/Java 风格,Dart 不推荐
使用 dart format 自动格式化
不用死记规范,只需在项目目录下运行:
$ dart format .
Dart 官方格式化工具会自动把代码调整为标准风格,保存时 VS Code 也可以配置自动格式化。
常见错误与解读
初学者写第一个程序时经常遇到以下错误,来认识一下它们。
错误一:忘记分号
实例
print('Hello, Dart!') // 缺少 ;
}
报错信息:
Error: Expected ';' after this.
解决方法:在语句末尾加上 ;。
错误二:括号不配对
实例
print('Hello, Dart!' // 缺少右括号 )
}
报错信息:
Error: Expected ')' before this.
解决方法:仔细检查每个 ( 是否都有对应的 )。VS Code 会高亮显示不匹配的括号。
错误三:字符串引号不匹配
void main() {
print('Hello, Dart!"); // 一个单引号、一个双引号
}
报错信息:
Error: Unterminated string literal.
解决方法:确保字符串两端用同一种引号。
错误四:main 拼写错误
实例
print('Hello, Dart!');
}
Dart 区分大小写,Main 和 main 是完全不同的名字。
程序能编译,但运行时会报错:
Error: No 'main' method found.
解决方法:入口函数必须是小写的 main。
错误五:变量在使用前未赋值
实例
String name;
print(name); // name 未初始化
}
Dart 空安全机制的报错:
Error: Non-nullable variable 'name' must be assigned before it can be used.
解决方法:声明变量时同时赋初值,或声明为可空类型 String? name(后续章节详细介绍)。
