仓颉编程语言中的包探索
【顺便谈一谈个人感受,目前仓颉(LTS 1.0.0)的包尚不太完善,仅是达到 “最小可用闭环”——目录即包、import 路径清晰、编译单元边界明确。但距离“好用”还有可见差距。官方文档不太好懂也不太精确,实验测试过程比较曲折。我是在windows10中,使用目前最新的实验环境:CodeArts IDE for Cangjie 3.4.1和2025 年 7 月推出首个长期支持版本(LTS 1.0.0)。一己之言,仅供参考。
以包(Package)的形式进行组织,包是最小的编译单元。包可以定义子包,从而构成树形结构。没有父包的包称为 root(根)包,root 包及其子包(包括子包的子包)构成的整棵树称为模块(module)。
包由一个或多个源码文件组成,同一个包的源码文件必须在同一个目录。一个包中可以包含多个源文件。模块(module)是若干包(Package)的集合。在仓颉编程语言中,一个模块根目录下的顶层最多只能有一个作为程序入口的 main 函数。
在仓颉编程语言中,可以通过 import fullPackageName.itemName 的语法导入其他包中的一个顶层声明或定义,fullPackageName 为完整路径包名,itemName 为声明的名字。
如果要导入的多个 itemName 同属于一个 fullPackageName,可以使用 import fullPackageName.{itemName1, itemName2, …} 语法
还可以使用 import packageName.* 语法将 packageName 包中所有可见的顶层声明或定义全部导入。
使用 import as 对导入的声明进行重命名后,当前包只能使用重命名后的新名字,原名无法使用。
仓颉编程语言中包中,同名标识符怎么导入使用?
目前可行的办法是用import … as 给每个同名标识符分别起别名。
我的测试实验的工程(Project)目录结构如下:
demoA ← 模块根(root)目录——工程(Project)名称
└── src ← 源码根目录
├── main.cj ← 模块入口
├── c.cj
└── directory_0 ← 包 demoA.directory_0
├── a.cj
├── c.cj
└── directory_1 ← 包 demoA.directory_0.directory_1
└── b.cj
源文件
src/directory_0/directory_1/b.cj文件内容:
package demoA.directory_0.directory_1
public func helloB() {
println("demoA.directory_0.directory_1 中 b.cj文件的helloB()")
}
src/directory_0/a.cj文件内容:
package demoA.directory_0
public func helloA() {
println("demoA.directory_0 中 a.cj文件的helloA()")
}
public func helloB() {
println("demoA.directory_0 中 a.cj文件的helloB()")
}
src/directory_0/c.cj文件内容:
package demoA.directory_0 // 首行必须是 package 声明
public func helloC() {
println("demoA.directory_0 中 c.cj文件的helloC()")
}
src/c.cj文件内容:
package demoA
public func helloC() {
println("demoA.directory_0 中 c.cj文件的helloC()")
}
src/main.cj文件内容:
package demoA
import demoA.directory_0.*
import demoA.directory_0.directory_1.helloB as helloB2
import demoA.directory_0.helloC as helloC2
main(): Int64 {
println("hello world")
helloC()
helloA()
helloB()
helloC2()
helloB2()
return 0
}
编译运行截图:
【顺便提示,如何在CodeArts IDE for Cangjie 创建的工程(Project) 源码根目录src上新建源码文件或子目录?
右击src可见相关快捷菜单命令项。】
请对输出
hello world
demoA.directory_0 中 c.cj文件的helloC()
demoA.directory_0 中 a.cj文件的helloA()
demoA.directory_0 中 a.cj文件的helloB()
demoA.directory_0 中 c.cj文件的helloC()
demoA.directory_0.directory_1 中 b.cj文件的helloB()
仔细分析体会。
分析提示:
1.目录层级与包声明完全一致
demoA/src/directory_0/ → package demoA.directory_0
demoA/src/directory_0/directory_1/ → package demoA.directory_0.directory_1
2.同名符号分布
helloB 同时出现在
– demoA.directory_0(a.cj)
– demoA.directory_0.directory_1(b.cj)
helloC 同时出现在
– demoA(c.cj)
– demoA.directory_0(c.cj)
3.导入方式
– import demoA.directory_0.*
把 demoA.directory_0 里所有可见符号一次性导入。
因为 demoA.directory_0 和 demoA 都有 helloC,为了避免歧义,所以在后面又单独写了一句:
import demoA.directory_0.helloC as helloC2 —— 显式起别名区分。
– helloB 同理:通过 import … as helloB2 显式起别名区分。
4. 仓颉语言的源码根目录src本身不会出现在包路径和import路径里,写上将出错,它只是文件系统的边界标记,而不是逻辑命名空间的一部分——这一点和Java语言类似。仓颉的项目名(模块名)必须出现在源码路径的最外层——这一点和Java语言不同。
例如,前面提到的示例中
src/directory_0/a.cj文件内容第一句
package demoA.directory_0 ,不能写为package demoA.src.directory_0
并且,在其它代码文件中如 模块入口文件main.cj 导入这个文件中的函数使用时
import demoA.directory_0.* ,不能写为import demoA.src.directory_0.*
另一个仓颉语言包示例:演示包结构和访问修饰符的使用 https://blog.csdn.net/cnds123/article/details/150225446
附录
工程文件目录结构是指在一个工程项目中,为了有效管理和组织各类文件而建立的目录层次结构。一个合理的目录结构能够帮助团队成员更清晰地了解项目的组成部分,提高工作效率。
工程文件目录结构浅谈 https://blog.csdn.net/cnds123/article/details/137046361