当前位置: 首页 > news >正文

【仓颉纪元】仓颉学习深度实践:30 天从零基础到独立开发

文章目录

  • 前言
  • 一、环境搭建(5 分钟)
    • 1.1、开发工具选择与安装
    • 1.2、Hello World 程序实战
  • 二、基础语法(10 分钟)
    • 2.1、变量声明与作用域
    • 2.2、基本数据类型详解
    • 2.3、运算符与表达式
    • 2.4、控制流语句
      • 2.4.1、if-else 条件语句
      • 2.4.2、match 模式匹配
      • 2.4.3、循环语句
  • 三、函数(5 分钟)
    • 3.1、函数定义与参数
    • 3.2、Lambda 表达式与闭包
  • 四、数据结构(5 分钟)
    • 4.1、数组基础操作
    • 4.2、ArrayList 动态数组
    • 4.3、HashMap 键值对存储
  • 五、面向对象(5 分钟)
    • 5.1、类与对象基础
    • 5.2、继承与多态
    • 5.3、接口与抽象
  • 六、可空类型与错误处理(3 分钟)
    • 6.1、可空类型与空安全
    • 6.2、Result 类型错误处理
    • 6.3、异常捕获与处理
  • 七、实用示例(2 分钟)
    • 7.1、简易计算器实现
    • 7.2、学生成绩管理系统
    • 7.3、待办事项管理应用
  • 八、常见问题与技巧
    • 8.1、字符串操作技巧
    • 8.2、数组高级操作
    • 8.3、类型别名与泛型
  • 九、学习路线建议
    • 9.1、初学者学习路线
    • 9.2、进阶开发路线
    • 9.3、学习资源推荐
  • 十、快速参考卡片
    • 10.1、语法快速参考
    • 10.2、常用 API 参考
  • 十一、关于作者与学习资源
    • 11.1、作者简介
    • 11.2、学习资源
  • 总结


前言

2024 年 10 月底华为发布仓颉编程语言,作为大数据开发工程师和 CSDN 成都站主理人,我意识到这是抓住新语言红利期的机会。HDC 2024 大会上仓颉的性能和安全性演示让我印象深刻,社区成员对仓颉学习需求很大,每周都有人问我如何入门。11 月 4 日开始学习之旅,两个月里我不仅系统学习了仓颉,还帮助 15 位朋友成功入门,在这个过程中总结出一套高效的学习方法。本文目标是让开发者在 30 天内从零基础到能够独立开发简单应用,通过实际代码示例而非枯燥理论讲解,配合详细注释和常见问题解答,采用循序渐进的方式从基础语法到面向对象再到实战项目,帮助你快速建立对这门语言的整体认知并掌握核心开发技能,为深入学习和实战开发打下坚实基础。

在这里插入图片描述


声明:本文由作者“白鹿第一帅”于 CSDN 社区原创首发,未经作者本人授权,禁止转载!爬虫、复制至第三方平台属于严重违法行为,侵权必究。亲爱的读者,如果你在第三方平台看到本声明,说明本文内容已被窃取,内容可能残缺不全,强烈建议您移步“白鹿第一帅” CSDN 博客查看原文,并在 CSDN 平台私信联系作者对该第三方违规平台举报反馈,感谢您对于原创和知识产权保护做出的贡献!

文章作者:白鹿第一帅,作者主页:https://blog.csdn.net/qq_22695001,未经授权,严禁转载,侵权必究!

一、环境搭建(5 分钟)

我的环境搭建经历(Day 1,11 月 4 日),学习任何编程语言的第一步都是搭建开发环境。我在 11 月 4 日开始学习仓颉时,环境搭建花了我整整一个下午。不是因为难,而是因为选择太多,不知道该用哪种方式。选择困难症:IDE 还是命令行?

编程初学者
有经验开发者
喜欢图形界面
喜欢命令行
开发工具选择
你的经验?
DevEco Studio
偏好?
命令行工具
优势
代码提示
可视化调试
项目管理
插件生态
优势
轻量快速
脚本自动化
远程开发

开发工具对比

特性DevEco Studio命令行工具推荐人群
学习曲线⭐⭐⭐⭐⭐⭐⭐⭐初学者 vs 老手
代码提示✅ 完善❌ 无需要提示的开发者
调试功能✅ 可视化⚠️ 命令行需要调试的项目
启动速度⭐⭐⭐⭐⭐⭐⭐⭐快速验证代码
项目管理✅ 完善⚠️ 手动大型项目
资源占用2GB+<100MB配置较低的电脑
适合场景完整项目开发快速脚本验证-

最初我纠结于两个选择:

  1. 使用 DevEco Studio(图形化 IDE,功能强大)
  2. 使用命令行工具(轻量级,适合老手)

作为一个习惯用 VSCode 的开发者,我最初想用命令行工具。但尝试后发现,DevEco Studio 的代码提示、调试功能、项目管理都很完善,特别适合初学者。最终我选择了 DevEco Studio,这个决定让我后续的学习效率提升了很多。

给初学者的建议

  • 如果你是编程初学者,强烈推荐 DevEco Studio
  • 如果你有丰富的编程经验,可以尝试命令行工具
  • 两种方式可以并存,根据场景选择

1.1、开发工具选择与安装

方式一:使用 DevEco Studio(推荐初学者),DevEco Studio 是华为官方提供的集成开发环境,专为鸿蒙和仓颉开发设计。它提供了代码补全、语法高亮、调试工具、项目管理等功能,大大提升开发效率。

安装步骤:

  1. 访问华为开发者官网,下载 DevEco Studio
  2. 安装完成后,打开 IDE,在插件市场搜索“Cangjie”
  3. 安装仓颉插件,重启 IDE
  4. 创建新项目:File -> New -> Cangjie Project

我的安装经验

下载阶段
下载阶段
访问官网
访问官网
下载安装包
下载安装包
等待下载完成
等待下载完成
安装阶段
安装阶段
运行安装程序
运行安装程序
选择安装路径
选择安装路径
等待安装
等待安装
配置阶段
配置阶段
首次启动
首次启动
下载SDK
下载SDK
安装插件
安装插件
配置完成
配置完成
DevEco Studio 安装历程
步骤时间注意事项
下载安装包10-30 分钟约 2GB,需要预留足够空间
安装程序5-10 分钟选择合适的安装路径
首次启动2-3 分钟会进行初始化配置
下载 SDK10-15 分钟建议配置国内镜像源
安装插件3-5 分钟搜索“Cangjie”插件
总计30-60 分钟一次性投入,后续高效
  • 下载大小约 2GB,需要预留足够空间
  • 首次启动会下载 SDK,需要等待 10-15 分钟
  • 建议配置国内镜像源,加快下载速度

方式二:使用命令行工具(适合有经验的开发者),命令行工具轻量级,启动快,适合快速验证代码。如果你习惯用 Vim、Emacs 或 VSCode,可以选择这种方式。

# 安装仓颉编译器(通过DevEco Studio)
# 请访问华为开发者官网下载DevEco Studio
# https://developer.huawei.com/consumer/cn/deveco-studio/# 验证安装
cjc --version# 创建新项目
cjc new hello-cangjie
cd hello-cangjie

1.2、Hello World 程序实战

Hello World 的意义(Day 1 下午),写第一个程序时,我很激动。虽然只是简单的“Hello World”,但它标志着学习的开始。很多人觉得 Hello World 没意义,但我认为它很重要:

  1. 验证环境搭建是否成功
  2. 熟悉编译和运行流程
  3. 建立信心,迈出第一步

我的第一次尝试,创建 main.cj 文件:

// 这是注释
main() {println("你好,仓颉!")println("Hello, Cangjie!")
}

代码说明

  • main():程序的入口函数,类似 Java 的 main 方法
  • println():打印函数,会自动换行
  • //:单行注释,编译器会忽略
  • 字符串用双引号包裹,支持中文

运行程序:

cjc run main.cj

输出:

你好,仓颉!
Hello, Cangjie!

第一次运行的感受,当我看到输出时,虽然只是两行文字,但心里很有成就感。这说明环境搭建成功了,我可以开始真正的学习了。

cjc run
编译失败
修复错误
编译成功
成功!
编写代码
编译
检查错误
运行
查看输出
常见错误:
- 语法错误
- 拼写错误
- 编码问题

常见问题

  1. 如果提示“cjc: command not found”,说明环境变量没配置好
  2. 如果提示编译错误,检查代码是否有拼写错误
  3. 如果中文显示乱码,检查文件编码是否为 UTF-8

二、基础语法(10 分钟)

学习方法建议(Day 2-5,11 月 5-8 日),基础语法是学习的重点,也是最容易放弃的阶段。很多人觉得语法枯燥,看了就忘。我的经验是:不要死记硬背,要通过实践来学习。

我的学习方法

看语法点
写代码验证
理解了吗?
写更多例子
记录笔记
第二天复习
进入下一个
  1. 看一个语法点,立即写代码验证
  2. 不理解的地方,写多个例子尝试
  3. 每天学习 2-3 个语法点,不贪多
  4. 第二天复习前一天的内容

学习效果对比

学习方式记忆效果理解深度时间投入推荐度
只看不练⭐⭐⭐⭐1 小时/天
看完就练⭐⭐⭐⭐⭐⭐⭐⭐2 小时/天
大量练习⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐3 小时/天✅✅

这个方法让我在 4 天内掌握了基础语法,而且记得很牢。

2.1、变量声明与作用域

变量是什么?(Day 2 上午),变量就是存储数据的容器。学习变量时,我最初不理解 let 和 var 的区别,写了很多代码才明白:

  • let:声明不可变变量,一旦赋值就不能改变
  • var:声明可变变量,可以多次赋值

为什么要区分可变和不可变? 这是我学习仓颉时的第一个困惑。后来我理解了:

  1. 不可变变量更安全,不会被意外修改
  2. 不可变变量便于编译器优化
  3. 函数式编程推荐使用不可变变量

在实际开发中,我发现 80% 的变量都可以用 let,只有需要修改的才用 var。这让代码更安全、更易维护。

main() {// 使用 let 声明不可变变量(推荐)let name: String = "张三"let age: Int64 = 25// 类型推断(编译器自动推断类型)let city = "北京"  // 自动推断为 Stringlet score = 95     // 自动推断为 Int64// 使用 var 声明可变变量var count = 0count = count + 1  // 可以修改println("姓名: ${name}, 年龄: ${age}")println("城市: ${city}, 分数: ${score}")println("计数: ${count}")
}

关键点

  • let 声明不可变变量(类似 Java 的 final)
  • var 声明可变变量
  • 支持类型推断,可以省略类型声明
  • 使用 ${变量} 进行字符串插值

2.2、基本数据类型详解

数据类型的重要性(Day 2 下午),学习数据类型时,我最初觉得很无聊:为什么要区分 Int8、Int16、Int32、Int64?直接用一个 Int 不行吗?

后来我理解了:不同的数据类型占用不同的内存空间。Int8 只占 1 字节,Int64 占 8 字节。在处理大量数据时,选择合适的类型可以节省内存。

在我的大数据项目中,有一个字段存储年龄(0-120)。如果用 Int64,每个值占 8 字节;如果用 Int8,只占 1 字节。处理 1 亿条数据时,可以节省 700MB 内存!

类型选择建议

数据类型内存占用数值范围适用场景示例
Int81 字节-128~127年龄、等级年龄: 25
Int162 字节-32768~32767端口号、计数端口: 8080
Int324 字节-21 亿~21 亿ID、数量用户 ID
Int648 字节超大范围默认整数时间戳
Float324 字节7 位精度一般小数温度: 25.5
Float648 字节15 位精度默认小数科学计算
Bool1 字节true/false开关状态是否登录
String可变任意文本文本数据用户名
main() {// 整数类型let int8: Int8 = 127           // 8位整数let int16: Int16 = 32767       // 16位整数let int32: Int32 = 2147483647  // 32位整数let int64: Int64 = 9223372036854775807  // 64位整数(默认)// 浮点类型let float32: Float32 = 3.14let float64: Float64 = 2.718281828  // 默认浮点类型// 布尔类型let isStudent: Bool = truelet isGraduated: Bool = false// 字符和字符串let char: Rune = 'A'  // 单个字符(Unicode)let text: String = "仓颉语言"// 类型转换let num = 42let numFloat = Float64(num)  // 显式转换let numStr = num.toString()  // 转为字符串println("整数: ${int64}")println("浮点: ${float64}")println("布尔: ${isStudent}")println("字符串: ${text}")
}

2.3、运算符与表达式

main() {// 算术运算符let a = 10let b = 3println("加法: ${a + b}")      // 13println("减法: ${a - b}")      // 7println("乘法: ${a * b}")      // 30println("除法: ${a / b}")      // 3println("取模: ${a % b}")      // 1// 比较运算符println("相等: ${a == b}")     // falseprintln("不等: ${a != b}")     // trueprintln("大于: ${a > b}")      // trueprintln("小于: ${a < b}")      // falseprintln("大于等于: ${a >= b}") // trueprintln("小于等于: ${a <= b}") // false// 逻辑运算符let x = truelet y = falseprintln("与: ${x && y}")       // falseprintln("或: ${x || y}")       // trueprintln("非: ${!x}")           // false// 位运算符let m = 5   // 二进制: 0101let n = 3   // 二进制: 0011println("按位与: ${m & n}")    // 1 (0001)println("按位或: ${m | n}")    // 7 (0111)println("按位异或: ${m ^ n}")  // 6 (0110)println("左移: ${m << 1}")     // 10 (1010)println("右移: ${m >> 1}")     // 2 (0010)
}

2.4、控制流语句

控制流语句决定程序的执行顺序,是编程的核心概念。仓颉提供了丰富的控制流语句,包括条件判断、循环、跳转等。

控制流的重要性

  • 逻辑控制:根据条件执行不同的代码分支
  • 重复执行:使用循环处理批量数据
  • 程序结构:让程序逻辑更清晰
  • 效率提升:避免重复编写相似代码

2.4.1、if-else 条件语句

main() {let score = 85// 基本 if-elseif (score >= 90) {println("优秀")} else if (score >= 80) {println("良好")} else if (score >= 60) {println("及格")} else {println("不及格")}// if 表达式(可以返回值)let grade = if (score >= 60) { "通过" } else { "未通过" }println("结果: ${grade}")// 简洁写法let status = if (score >= 60) "及格" else "不及格"println("状态: ${status}")
}

2.4.2、match 模式匹配

main() {let day = 3// 基本 matchmatch (day) {case 1 => println("星期一")case 2 => println("星期二")case 3 => println("星期三")case 4 => println("星期四")case 5 => println("星期五")case 6 | 7 => println("周末")  // 多个值case _ => println("无效")      // 默认分支}// match 表达式let dayName = match (day) {case 1 => "Monday"case 2 => "Tuesday"case 3 => "Wednesday"case 4 => "Thursday"case 5 => "Friday"case 6 | 7 => "Weekend"case _ => "Invalid"}println("Day: ${dayName}")
}

2.4.3、循环语句

main() {// for 循环(范围)println("=== for 循环 ===")for (i in 0..5) {  // 0 到 4println("i = ${i}")}// for 循环(包含结束值)for (i in 0..=5) {  // 0 到 5println("i = ${i}")}// for 循环(步长)for (i in 0..10 step 2) {  // 0, 2, 4, 6, 8println("i = ${i}")}// 遍历数组let fruits = ["苹果", "香蕉", "橙子"]for (fruit in fruits) {println("水果: ${fruit}")}// while 循环println("=== while 循环 ===")var count = 0while (count < 3) {println("count = ${count}")count += 1}// do-while 循环println("=== do-while 循环 ===")var num = 0do {println("num = ${num}")num += 1} while (num < 3)// break 和 continueprintln("=== break 和 continue ===")for (i in 0..10) {if (i == 3) {continue  // 跳过 3}if (i == 7) {break     // 在 7 处停止}println("i = ${i}")}
}

三、函数(5 分钟)

函数的本质(Day 6-7,11月 9-10 日),学习函数时,我终于理解了编程的精髓:复用。函数就是把重复的代码封装起来,需要时调用,避免重复编写。

代码对比:重复 vs 函数

函数方式
重复代码方式
定义 printSum 函数
调用 printSum10,20
调用 printSum30,40
调用 printSum50,60
打印结果
计算 10+20
打印结果
计算 30+40
打印结果
计算 50+60

Day 6 上午,我写了一个计算器程序,代码重复严重:

// 重复的代码
let result1 = 10 + 20
println("10 + 20 = ${result1}")let result2 = 30 + 40
println("30 + 40 = ${result2}")let result3 = 50 + 60
println("50 + 60 = ${result3}")

Day 6 下午,我学会了函数,代码简洁多了:

func printSum(a: Int64, b: Int64) {println("${a} + ${b} = ${a + b}")
}printSum(10, 20)
printSum(30, 40)
printSum(50, 60)

这个对比让我深刻理解了函数的价值。函数的好处

对比项不使用函数使用函数改进
代码行数15 行7 行⬇️ 53%
重复代码3 处0 处⬇️ 100%
维护成本修改 3 处修改 1 处⬇️ 67%
可读性⭐⭐⭐⭐⭐⭐⭐⬆️ 150%
可测试性⭐⭐⭐⭐⭐⭐⭐⬆️ 150%

3.1、函数定义与参数

函数的组成部分,一个完整的函数包含:

  1. 函数名:描述函数的功能
  2. 参数列表:函数需要的输入
  3. 返回类型:函数的输出类型
  4. 函数体:具体的实现逻辑

命名建议

规范好的示例不好的示例说明
动词开头getUserName()userName()表明这是一个动作
有意义calculateTotalScore()calc()清晰表达功能
驼峰命名printStudentInfo()print_student_info()遵循语言规范
避免缩写getMaximumValue()getMaxVal()完整单词更清晰
  • 使用动词开头:get、set、calculate、print
  • 名称要有意义:getUserName 而不是 getName
  • 遵循驼峰命名:calculateTotalScore
// 基本函数
func greet(name: String): Unit {println("你好, ${name}!")
}// 带返回值的函数
func add(a: Int64, b: Int64): Int64 {return a + b
}// 表达式函数(单行)
func multiply(a: Int64, b: Int64): Int64 = a * b// 默认参数
func power(base: Int64, exponent: Int64 = 2): Int64 {var result: Int64 = 1for (_ in 0..exponent) {result *= base}return result
}// 可变参数
func sum(numbers: Int64...): Int64 {var total: Int64 = 0for (num in numbers) {total += num}return total
}main() {greet("张三")let result1 = add(10, 20)println("10 + 20 = ${result1}")let result2 = multiply(5, 6)println("5 * 6 = ${result2}")println("2^2 = ${power(2)}")      // 使用默认参数println("2^3 = ${power(2, 3)}")   // 指定参数println("总和: ${sum(1, 2, 3, 4, 5)}")
}

3.2、Lambda 表达式与闭包

main() {// Lambda 表达式let square = { x: Int64 => x * x }println("5的平方: ${square(5)}")// 多参数 Lambdalet add = { x: Int64, y: Int64 => x + y }println("3 + 7 = ${add(3, 7)}")// 高阶函数func applyOperation(a: Int64, b: Int64, op: (Int64, Int64) -> Int64): Int64 {return op(a, b)}let result1 = applyOperation(10, 5, { x, y => x + y })let result2 = applyOperation(10, 5, { x, y => x - y })let result3 = applyOperation(10, 5, { x, y => x * y })println("10 + 5 = ${result1}")println("10 - 5 = ${result2}")println("10 * 5 = ${result3}")
}

四、数据结构(5 分钟)

4.1、数组基础操作

main() {// 创建数组let numbers = [1, 2, 3, 4, 5]let fruits = ["苹果", "香蕉", "橙子"]// 访问元素println("第一个数字: ${numbers[0]}")println("第二个水果: ${fruits[1]}")// 数组长度println("数组长度: ${numbers.size}")// 修改元素(需要 var)var mutableArray = [10, 20, 30]mutableArray[0] = 15println("修改后: ${mutableArray[0]}")// 数组方法let doubled = numbers.map({ x => x * 2 })println("翻倍: ${doubled}")let evens = numbers.filter({ x => x % 2 == 0 })println("偶数: ${evens}")let sum = numbers.reduce(0, { acc, x => acc + x })println("总和: ${sum}")
}

4.2、ArrayList 动态数组

main() {// 创建 ArrayListvar list = ArrayList<Int64>()// 添加元素list.append(10)list.append(20)list.append(30)println("列表: ${list}")println("大小: ${list.size}")// 插入元素list.insert(1, 15)  // 在索引1处插入15println("插入后: ${list}")// 删除元素list.remove(2)println("删除后: ${list}")// 遍历for (item in list) {println("元素: ${item}")}
}

4.3、HashMap 键值对存储

main() {// 创建 HashMapvar scores = HashMap<String, Int64>()// 添加键值对scores["张三"] = 95scores["李四"] = 87scores["王五"] = 92// 获取值if (let score = scores["张三"]) {println("张三的分数: ${score}")}// 检查键是否存在if (scores.containsKey("李四")) {println("李四的成绩已录入")}// 遍历for ((name, score) in scores) {println("${name}: ${score}分")}// 删除scores.remove("王五")println("删除后大小: ${scores.size}")
}

五、面向对象(5 分钟)

面向对象的顿悟时刻(Day 11-13,11 月 14-16 日),学习面向对象时,我经历了从困惑到顿悟的过程。最初我不理解:为什么要用类?函数不够用吗?

我的理解过程

上午
上午
用函数实现学生管理
用函数实现学生管理
发现数据分散问题
发现数据分散问题
感到困惑
感到困惑
下午
下午
学习类的概念
学习类的概念
用类重构代码
用类重构代码
顿悟时刻
顿悟时刻
Day 11 面向对象学习历程

Day 11 上午,我写了一个学生管理程序,用函数实现:

var studentNames = ["张三", "李四", "王五"]
var studentAges = [20, 21, 19]
var studentScores = [95, 87, 92]func printStudent(index: Int64) {println("${studentNames[index]}, ${studentAges[index]}岁, ${studentScores[index]}分")
}

这个代码的问题分析

问题描述影响严重程度
数据分散三个数组分别存储难以管理,容易遗漏⭐⭐⭐⭐
同步困难三个数组要保持一致容易出现索引错位⭐⭐⭐⭐⭐
扩展困难添加字段要改多处维护成本高⭐⭐⭐⭐
可读性差数据关系不明确理解困难⭐⭐⭐

Day 11 下午,我学会了类,代码清晰多了:

class Student {var name: Stringvar age: Int64var score: Int64func print() {println("${name}, ${age}岁, ${score}分")}
}let students = [Student("张三", 20, 95),Student("李四", 21, 87),Student("王五", 19, 92)
]

这个对比让我理解了面向对象的价值:把相关的数据和操作封装在一起,代码更清晰、更易维护。

什么时候用类?

  • 数据和操作相关时(如学生的信息和操作)
  • 需要创建多个相似对象时(如多个学生)
  • 需要继承和多态时(如动物类的不同子类)

5.1、类与对象基础

类和对象的关系,类是模板,对象是实例。就像:

  • 类是“学生”这个概念
  • 对象是具体的“张三”、“李四”

类的组成

  1. 属性(数据):描述对象的特征
  2. 方法(操作):描述对象的行为
  3. 构造函数:创建对象时的初始化逻辑
// 定义类
class Person {// 属性var name: Stringvar age: Int64// 构造函数init(name: String, age: Int64) {this.name = namethis.age = age}// 方法func introduce(): Unit {println("我叫${name},今年${age}岁")}func haveBirthday(): Unit {age += 1println("${name}过生日了,现在${age}岁")}
}main() {// 创建对象let person1 = Person("张三", 25)let person2 = Person("李四", 30)// 调用方法person1.introduce()person2.introduce()person1.haveBirthday()
}

5.2、继承与多态

// 基类
class Animal {var name: Stringinit(name: String) {this.name = name}func makeSound(): Unit {println("${name}发出声音")}
}// 派生类
class Dog <: Animal {var breed: Stringinit(name: String, breed: String) {super.init(name)this.breed = breed}// 重写方法override func makeSound(): Unit {println("${name}(${breed})汪汪叫")}func fetch(): Unit {println("${name}去捡球")}
}class Cat <: Animal {init(name: String) {super.init(name)}override func makeSound(): Unit {println("${name}喵喵叫")}
}main() {let dog = Dog("旺财", "金毛")let cat = Cat("咪咪")dog.makeSound()dog.fetch()cat.makeSound()
}

5.3、接口与抽象

// 定义接口
interface Drawable {func draw(): Unit
}interface Movable {func move(x: Int64, y: Int64): Unit
}// 实现接口
class Circle <: Drawable, Movable {var x: Int64var y: Int64var radius: Int64init(x: Int64, y: Int64, radius: Int64) {this.x = xthis.y = ythis.radius = radius}func draw(): Unit {println("在(${x}, ${y})绘制半径为${radius}的圆")}func move(newX: Int64, newY: Int64): Unit {x = newXy = newYprintln("圆移动到(${x}, ${y})")}
}main() {let circle = Circle(10, 20, 5)circle.draw()circle.move(30, 40)circle.draw()
}

六、可空类型与错误处理(3 分钟)

6.1、可空类型与空安全

main() {// 可空类型声明let name: String? = getUserName()  // 可能为空// 安全调用if (let actualName = name) {println("用户名: ${actualName}")} else {println("用户名为空")}// 空值合并运算符let displayName = name ?? "访客"println("显示名称: ${displayName}")// 链式调用let length = name?.length ?? 0println("名称长度: ${length}")
}func getUserName(): String? {// 模拟可能返回空值的函数let random = Math.random()if (random > 0.5) {return Some("张三")} else {return None}
}

6.2、Result 类型错误处理

// Result 类型用于错误处理
enum Result<T, E> {| Success(T)| Failure(E)
}func divide(a: Int64, b: Int64): Result<Int64, String> {if (b == 0) {return Result.Failure("除数不能为零")}return Result.Success(a / b)
}main() {let result1 = divide(10, 2)match (result1) {case Success(value) => println("结果: ${value}")case Failure(error) => println("错误: ${error}")}let result2 = divide(10, 0)match (result2) {case Success(value) => println("结果: ${value}")case Failure(error) => println("错误: ${error}")}
}

6.3、异常捕获与处理

func readFile(path: String): String {try {// 尝试读取文件let content = FileSystem.read(path)return content} catch (e: FileNotFoundException) {println("文件不存在: ${e.message}")return ""} catch (e: IOException) {println("IO错误: ${e.message}")return ""} finally {println("清理资源")}
}main() {let content = readFile("data.txt")println("文件内容: ${content}")
}

七、实用示例(2 分钟)

实战项目的重要性(Day 20-25,11 月 23-28 日),学完基础语法后,我开始做实战项目。这是学习过程中最重要的阶段,也是最有成就感的阶段。为什么要做实战项目?

  1. 巩固知识:理论和实践结合,记得更牢
  2. 发现问题:实战中会遇到各种问题,解决问题的过程就是学习
  3. 建立信心:完成一个项目,会有很大的成就感
  4. 积累经验:实战经验比理论知识更有价值

我的实战经历
Day 20-21:做了一个计算器程序,学会了函数和错误处理
Day 22-23:做了一个学生成绩管理系统,学会了类和数据结构
Day 24-25:做了一个待办事项列表,学会了枚举和状态管理

这三个项目让我对仓颉有了全面的理解,也让我有信心开发更复杂的应用。

项目选择建议

  1. 从简单开始:计算器、猜数字游戏
  2. 逐步提升:学生管理、图书管理
  3. 挑战自己:天气应用、聊天程序

7.1、简易计算器实现

项目背景:计算器是一个经典的入门项目。它涉及函数、条件判断、错误处理等核心概念,非常适合练习。

功能需求

  1. 支持加减乘除四则运算
  2. 处理除零错误
  3. 返回计算结果或错误信息

设计思路

  1. 定义一个 calculator 函数,接受两个数和一个运算符
  2. 使用 match 模式匹配不同的运算符
  3. 使用可空类型处理错误情况

实现要点

  • 使用 Float64 支持小数运算
  • 使用可空类型(Float64?)表示可能失败的结果
  • 除法要检查除数是否为零
func calculator(a: Float64, b: Float64, operator: String): Float64? {match (operator) {case "+" => Some(a + b)case "-" => Some(a - b)case "*" => Some(a * b)case "/" => {if (b != 0.0) {Some(a / b)} else {None}}case _ => None}
}main() {println("=== 简易计算器 ===")let operations = [(10.0, 5.0, "+"), (10.0, 5.0, "-"), (10.0, 5.0, "*"), (10.0, 5.0, "/"),(10.0, 0.0, "/")]for ((a, b, op) in operations) {if (let result = calculator(a, b, op)) {println("${a} ${op} ${b} = ${result}")} else {println("${a} ${op} ${b} = 错误")}}
}

7.2、学生成绩管理系统

class Student {var name: Stringvar scores: HashMap<String, Int64>init(name: String) {this.name = namethis.scores = HashMap()}func addScore(subject: String, score: Int64): Unit {scores[subject] = score}func getAverage(): Float64 {if (scores.size == 0) {return 0.0}var total: Int64 = 0for ((_, score) in scores) {total += score}return Float64(total) / Float64(scores.size)}func printReport(): Unit {println("=== ${name}的成绩单 ===")for ((subject, score) in scores) {println("${subject}: ${score}分")}println("平均分: ${getAverage()}")}
}main() {let student = Student("张三")student.addScore("语文", 95)student.addScore("数学", 88)student.addScore("英语", 92)student.addScore("物理", 85)student.printReport()
}

7.3、待办事项管理应用

enum TaskStatus {| Pending| InProgress| Completedfunc toString(): String {match (this) {case Pending => "待办"case InProgress => "进行中"case Completed => "已完成"}}
}class Task {var id: Int64var title: Stringvar status: TaskStatusinit(id: Int64, title: String) {this.id = idthis.title = titlethis.status = TaskStatus.Pending}func start(): Unit {status = TaskStatus.InProgress}func complete(): Unit {status = TaskStatus.Completed}
}class TodoList {var tasks: ArrayList<Task>var nextId: Int64init() {this.tasks = ArrayList()this.nextId = 1}func addTask(title: String): Unit {let task = Task(nextId, title)tasks.append(task)nextId += 1println("已添加任务: ${title}")}func startTask(id: Int64): Unit {for (task in tasks) {if (task.id == id) {task.start()println("任务 ${id} 开始执行")return}}println("未找到任务 ${id}")}func completeTask(id: Int64): Unit {for (task in tasks) {if (task.id == id) {task.complete()println("任务 ${id} 已完成")return}}println("未找到任务 ${id}")}func listTasks(): Unit {println("=== 待办事项列表 ===")for (task in tasks) {println("[${task.id}] ${task.title} - ${task.status.toString()}")}}
}main() {let todoList = TodoList()todoList.addTask("学习仓颉语言")todoList.addTask("开发鸿蒙应用")todoList.addTask("写技术文章")todoList.listTasks()println("\n开始执行任务...")todoList.startTask(1)todoList.completeTask(1)println()todoList.listTasks()
}

八、常见问题与技巧

8.1、字符串操作技巧

main() {let text = "Hello, Cangjie!"// 字符串长度println("长度: ${text.length}")// 字符串拼接let greeting = "你好" + "," + "世界"println(greeting)// 字符串插值let name = "张三"let age = 25println("${name}今年${age}岁")// 字符串方法println("大写: ${text.toUpperCase()}")println("小写: ${text.toLowerCase()}")println("包含: ${text.contains("Cangjie")}")println("开头: ${text.startsWith("Hello")}")println("结尾: ${text.endsWith("!")}")// 字符串分割let parts = text.split(", ")for (part in parts) {println("部分: ${part}")}// 字符串替换let replaced = text.replace("Cangjie", "World")println("替换后: ${replaced}")
}

8.2、数组高级操作

main() {let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]// map: 转换每个元素let squared = numbers.map({ x => x * x })println("平方: ${squared}")// filter: 过滤元素let evens = numbers.filter({ x => x % 2 == 0 })println("偶数: ${evens}")// reduce: 归约let sum = numbers.reduce(0, { acc, x => acc + x })println("总和: ${sum}")// any: 是否存在满足条件的元素let hasLarge = numbers.any({ x => x > 5 })println("有大于5的数: ${hasLarge}")// all: 是否所有元素都满足条件let allPositive = numbers.all({ x => x > 0 })println("都是正数: ${allPositive}")// find: 查找第一个满足条件的元素if (let found = numbers.find({ x => x > 5 })) {println("第一个大于5的数: ${found}")}// 链式调用let result = numbers.filter({ x => x % 2 == 0 }).map({ x => x * x }).reduce(0, { acc, x => acc + x })println("偶数平方和: ${result}")
}

8.3、类型别名与泛型

// 定义类型别名
type UserId = Int64
type UserName = String
type Score = Int64class User {var id: UserIdvar name: UserNamevar score: Scoreinit(id: UserId, name: UserName, score: Score) {this.id = idthis.name = namethis.score = score}
}main() {let user = User(1001, "张三", 95)println("用户 ${user.name} (ID: ${user.id}) 得分: ${user.score}")
}

九、学习路线建议

我的 30 天学习计划(Day 26-30,11 月 29-12 月 3 日)

2024-11-052024-11-072024-11-092024-11-112024-11-132024-11-152024-11-172024-11-192024-11-212024-11-232024-11-252024-11-272024-11-292024-12-012024-12-03环境搭建 基础语法 函数与数据结构 面向对象 进阶特性 深入学习 标准库学习 并发编程 小型项目 中型项目 完整项目 基础阶段进阶阶段实战阶段30天学习路线图

在帮助 15 位朋友学习仓颉的过程中,我总结出了一套高效的学习路线。这个路线经过实践验证,80% 的人都能在 30 天内从零基础到独立开发。学习的三个阶段

基础阶段
第1-10天
进阶阶段
第11-20天
实战阶段
第21-30天
掌握语法
写简单程序
理解原理
解决问题
独立开发
完成项目

三个阶段对比

阶段时间目标学习重点学习方法成果
基础阶段第 1-10 天掌握语法变量、函数、类多练习,不求甚解能写简单程序
进阶阶段第 11-20 天理解原理内存、并发、优化多思考,理解原理能解决问题
实战阶段第 21-30 天独立开发项目实战多实践,解决问题能做完整项目
33%33%34%30天学习时间分配基础语法进阶学习实战项目

每个阶段的重点不同

  • 基础阶段:多练习,不求甚解
  • 进阶阶段:多思考,理解原理
  • 实战阶段:多实践,解决问题

9.1、初学者学习路线

第 1-3 天:基础语法(Day 1-3),这三天是最关键的,也是最容易放弃的。很多人觉得语法枯燥,看了就忘。我的建议是:

学习语法点
立即写代码
理解了?
写更多例子
记录笔记
第二天复习
记住了?
下一个语法点

学习建议

建议说明效果
每天 2-3 个语法点不贪多,求精通⭐⭐⭐⭐⭐
立即写代码验证实践出真知⭐⭐⭐⭐⭐
多写例子加深理解⭐⭐⭐⭐
第二天复习巩固记忆⭐⭐⭐⭐⭐
  1. 每天学习 2-3 个语法点,不贪多
  2. 每个语法点都要写代码验证
  3. 不理解的地方,多写几个例子
  4. 第二天复习前一天的内容

学习内容

  • Day 1:变量、数据类型、运算符
  • Day 2:控制流(if、match)
  • Day 3:循环(for、while)

学习方法

  • 看一个语法点,立即写代码
  • 不要死记硬背,要理解原理
  • 遇到问题,先自己思考,再查文档

第 4-5 天:函数和数据结构(Day 4-5),函数是编程的核心,一定要掌握好。数据结构是存储数据的方式,也很重要。

学习内容

  • Day 4:函数定义、参数、返回值、Lambda 表达式
  • Day 5:数组、ArrayList、HashMap

学习重点

  • 理解函数的作用:代码复用
  • 掌握数据结构的选择:什么时候用数组,什么时候用 HashMap
  • 练习高阶函数:map、filter、reduce

第 6-7 天:面向对象(Day 6-7),面向对象是编程思想的转变,从面向过程到面向对象。这个转变需要时间,不要着急。

学习内容

  • Day 6:类和对象、属性和方法
  • Day 7:继承、多态、接口

学习难点

  • 理解类和对象的关系
  • 理解继承的作用
  • 理解多态的意义

第 8-10 天:进阶特性(Day 8-10),进阶特性是仓颉的亮点,也是区别于其他语言的地方。

学习内容

  • Day 8:可空类型、空安全
  • Day 9:错误处理、Result 类型
  • Day 10:泛型基础

学习建议

  • 可空类型是仓颉的特色,一定要掌握
  • 错误处理要用 Result 类型,不要用异常
  • 泛型可以先了解,不需要深入

第 11-14 天:实战练习(Day 11-14)

实战练习
Day 11-12
计算器
Day 13
学生管理
Day 14
待办列表
函数练习
错误处理
用户输入
类的使用
数据结构
CRUD操作
枚举类型
状态管理
列表操作

实战是检验学习成果的最好方式。通过做项目,可以发现自己的不足,也可以巩固知识。

项目建议

天数项目难度练习重点预计时间
Day 11-12计算器程序⭐⭐⭐函数、错误处理4-6 小时
Day 13学生成绩管理⭐⭐⭐⭐类、数据结构3-4 小时
Day 14待办事项列表⭐⭐⭐⭐枚举、状态管理3-4 小时

实战开发流程

需求分析
设计方案
编写代码
测试验证
有问题?
调试修复
代码优化
完成项目

实战技巧

  • 先设计后编码:想清楚要做什么,再开始写代码
  • 遇到问题先思考:不要一遇到问题就查答案
  • 完成后优化:先实现功能,再优化代码

9.2、进阶开发路线

第 15-20 天:深入学习(Day 15-20)

深入学习阶段
标准库源码
内存管理
并发编程
性能优化
ArrayList实现
HashMap实现
String实现
所有权机制
借用规则
生命周期
协程基础
async/await
并发安全
性能分析
内存优化
算法优化

这个阶段要深入理解仓颉的核心特性,不仅要知道怎么用,还要知道为什么这样设计。

学习内容与时间分配

天数主题学习内容学习方法时间投入
Day 15-16标准库源码ArrayList、HashMap阅读源码、写笔记4 小时/天
Day 17-18内存管理所有权、借用实验验证、画图理解3 小时/天
Day 19并发编程协程、async/await写并发程序4 小时
Day 20性能优化分析工具、优化技巧性能测试4 小时

学习方法

  • 阅读官方文档,理解设计理念
  • 阅读标准库源码,学习最佳实践
  • 做性能测试,理解优化原理

第 21-30 天:实战项目(Day 21-30)

2024-11-242024-11-252024-11-262024-11-272024-11-282024-11-292024-11-302024-12-012024-12-022024-12-032024-12-042024-12-05确定项目方向 需求分析 架构设计 核心功能开发 UI开发 测试优化 文档编写 项目选择天气应用总结实战项目时间规划

这个阶段要做一个完整的项目,从需求分析到架构设计,从编码实现到测试部署。

项目建议

项目选择
天气应用
笔记应用
聊天应用
网络请求
UI开发
数据缓存
数据持久化
分布式同步
富文本编辑
并发编程
实时通信
消息队列
项目难度技术栈开发时间适合人群
天气应用⭐⭐⭐网络、UI、缓存7-9 天初学者
笔记应用⭐⭐⭐⭐持久化、同步8-10 天有基础
聊天应用⭐⭐⭐⭐⭐并发、实时通信9-10 天进阶者

项目要求

  • 功能完整:核心功能都要实现
  • 代码规范:遵循最佳实践
  • 有测试:至少有单元测试
  • 有文档:README 要写清楚

9.3、学习资源推荐

官方资源(必看)

资源类型重要性更新频率链接
仓颉语言官方文档文档⭐⭐⭐⭐⭐每周最权威的学习资料
HarmonyOS 开发者社区社区⭐⭐⭐⭐⭐每天有很多实战案例
DevEco Studio 教程教程⭐⭐⭐⭐每月学习 IDE 的使用

实践项目(必做)

实践项目
初级
中级
高级
命令行工具
基础语法
计算器
函数使用
数据处理
数据结构
GUI应用
UI开发
鸿蒙应用
分布式能力
完整项目
综合实战
  • 命令行工具:练习基础语法
  • 数据处理程序:练习数据结构和算法
  • GUI 应用:练习 UI 开发
  • 鸿蒙原生应用:练习分布式能力

社区资源(推荐)

  • GitHub 开源项目:学习优秀代码
  • 技术博客和文章:了解最新动态
  • 开发者论坛:交流学习心得

我的学习建议

学习建议
文档
项目
社区
实践
反复阅读
每次新收获
多读代码
学习风格
积极参与
加深理解
理论结合
实践为主
  1. 官方文档要反复看,每次都有新收获
  2. 开源项目要多读,学习别人的代码风格
  3. 社区要多参与,交流能加深理解
  4. 实践最重要,理论要结合实践

十、快速参考卡片

说明:以下是仓颉语言的快速参考,方便查阅常用语法和 API。建议收藏本节,在实际开发中随时查看。

10.1、语法快速参考

基础语法

  • 变量:let(不可变)、var(可变)
  • 函数:func name(params): ReturnType { }
  • 类:class Name { },接口:interface Name { }
  • 枚举:enum Name { | Case1 | Case2 }
  • 可空类型:Type?,安全解包:if (let v = value) { }

控制流

  • 条件:if (condition) { } else { }
  • 模式匹配:match (value) { case x => }
  • 循环:for (i in 0..10) { }while (condition) { }

数据结构

  • 数组:[1, 2, 3]
  • 动态数组:ArrayList<T>()
  • 哈希表:HashMap<K, V>()

函数式编程

  • Lambda:{ x: Int64 => x * x }
  • 高阶函数:mapfilterreduce

10.2、常用 API 参考

字符串操作

  • 长度:text.length
  • 大小写:toUpperCase()toLowerCase()
  • 查找:contains("sub")startsWith()endsWith()
  • 分割:split(",")
  • 替换:replace("old", "new")

数组操作

  • 大小:arr.size
  • 转换:map({ x => x * 2 })
  • 过滤:filter({ x => x > 0 })
  • 归约:reduce(0, { acc, x => acc + x })
  • 判断:any({ x => x > 5 })all({ x => x > 0 })

ArrayList 操作

  • 添加:append(item)insert(index, item)
  • 删除:remove(index)clear()
  • 访问:[index]size

HashMap 操作

  • 设置:map[key] = value
  • 获取:map.get(key)
  • 判断:containsKey(key)
  • 删除:remove(key)clear()

提示:完整的 API 文档请参考官方文档,这里只列出最常用的方法。

十一、关于作者与学习资源

11.1、作者简介

郭靖,笔名“白鹿第一帅”,大数据与大模型开发工程师,中国开发者影响力年度榜单人物。在编程语言教学和技术写作方面有丰富经验,擅长将复杂的技术概念用简洁易懂的方式呈现,帮助初学者快速上手新技术,已帮助数百名开发者成功转型。作为技术内容创作者,自 2015 年至今累计发布技术博客 300 余篇,全网粉丝超 60000+,获得 CSDN“博客专家”等多个技术社区认证,并成为互联网顶级技术公会“极星会”成员。

同时作为资深社区组织者,运营多个西南地区技术社区,包括 CSDN 成都站(10000+ 成员)、AWS User Group Chengdu、字节跳动 Trae Friends@Chengdu等,累计组织线下技术活动超 50 场,致力于推动技术交流与开发者成长。

CSDN 博客地址:https://blog.csdn.net/qq_22695001

11.2、学习资源

  • 仓颉语言官方教程
  • DevEco Studio 下载
  • 华为开发者学院
  • Kotlin 语言参考(语法相似)
  • Rust 程序设计语言(设计理念参考)

文章作者:白鹿第一帅,作者主页:https://blog.csdn.net/qq_22695001,未经授权,严禁转载,侵权必究!


总结

恭喜完成仓颉语言 30 天学习之旅!我们系统学习了变量声明、数据类型、控制流、函数、数据结构、面向对象、可空类型等核心语法,通过 30 多个代码示例和 3 个实用案例建立了对仓颉的整体认知。从我帮助 15 位朋友学习的经验看,掌握这些基础后就可以编写简单程序了,其中 80% 的人在学完后一周内就开发出了自己的第一个应用。学习建议:第一周巩固基础语法每天练习 2 小时,第二周学习类型系统和泛型深入理解编译期检查,第三周深入内存管理和并发编程掌握高性能开发技巧,第四周开始实战项目将所学知识融会贯通。学习编程最重要的是动手实践而不是死记硬背,建议完成文中所有示例代码并尝试扩展功能,遇到问题多查文档多思考。仓颉简洁而强大,特别适合鸿蒙原生应用开发,持续学习和实践你很快就能成为仓颉开发高手。

在这里插入图片描述


我是白鹿,一个不懈奋斗的程序猿。望本文能对你有所裨益,欢迎大家的一键三连!若有其他问题、建议或者补充可以留言在文章下方,感谢大家的支持!

http://www.dtcms.com/a/568986.html

相关文章:

  • RocketMQ【入门实践】
  • Harmony鸿蒙开发0基础入门到精通Day11--TypeScript篇
  • 网站做广告的好处软件定制开发平台
  • 从智能手表拆解看硬件与软件的魔法融合 -嵌入式开发
  • 【java基础语法】---- 综合训练
  • BKA-Transformer-LSTM多变量时间序列预测Matlab实现
  • 如何自己创造一个网站平台搬瓦工装WordPress
  • 数式Oinone亮相GOTC 2025开源集市,企业级产品化引擎冲击Gitee当日热门项目
  • 【产品研究】生物力学软件 SIMM 4.0 for Windows 用户手册总结
  • 更新公司网站内容需要山东住房和城乡建设局网站首页
  • Unity与Android原生交互开发入门篇 - 打开Android的设置
  • 如何查看Linux系统版本?
  • Python类和对象--生命周期方法(对象生命周期,内存管理机制-存储,垃圾回收)
  • PAIMON+STARROCKS 学习
  • *曲速引擎的核心思想
  • AI时代下医药项目管理效能提升与知识管理案例分享︱奥锐特药业研发中心主任庄守群
  • 路由器构建园区网
  • 陕西建设网站如何建立免费网站
  • 设计网站账号品牌策划公司广告语
  • 二十一、kubernetes 1.29 之 运维 03
  • 【论文精读】CMD:迈向高效视频生成的新范式
  • 技术实践 | 延趣游戏用户分层体系:基于TE系统实现精细化运营与流水增长
  • 【硬件SDK项目】uniapp框架设计与业务开发
  • 做推广必须知道的网站淮南网络建站公司
  • tcp 丢包分析
  • 基于改进Gerchberg–Saxton算法的全息图相位恢复方法研究
  • 【ISO8601】ISO8601 Rust 库完整学习指南
  • 辽宁沈阳做网站贷款公司网站模板
  • 【数论】乘法逆元(求逆元的三种方式)
  • c++ 引用包装器的用法