仓颉编程语言青少年基础教程:包(Package)
摘要:仓颉编程语言以包(Package)为基本编译单元,组织为树形结构。模块(module)由根包及其子包组成,是第三方发布的最小单元。每个源文件需声明所属包,包路径需与目录结构一致。导入时支持单个声明、批量导入及重命名机制,避免同名冲突。模块入口文件main.cj必须位于根目录,最多包含一个main函数。特别注意:项目名作为根包名且不可修改,src目录不参与包路径命名。示例展示了多级包结构、同名
仓颉编程语言青少年基础教程:包(Package)
在仓颉编程语言中,程序以包(Package)的形式进行组织,包是最小的编译单元。包可以定义子包,从而构成树形结构。没有父包的包称为 root(根)包,root 包及其子包(包括子包的子包)构成的整棵树称为模块(module)。一个包中可以包含多个源文件。
包路径应与文件系统目录结构一致。
模块是若干包的集合,是第三方开发者发布的最小单元。一个模块的程序入口只能在其根目录下,它的顶层最多只能有一个作为程序入口的 main ,该 main 没有参数或参数类型为 Array<String>,返回类型为整数类型或 Unit 类型。
【在 CodeArts IDE for Cangjie 中,当你新建一个工程(Project:工程/项目)时,你为工程所起的名称(Project Name),就会作为该工程的 root(根)包(Package)的名称,根包名一旦确定不要随意修改。root 包及其子包(包括子包的子包)构成的整棵树称为模块(module)。
在 CodeArts IDE for Cangjie 中新建工程时,你为工程指定的 Project Name 会被同时用作:
- 工程根目录名(Project Name)
- root 包名
- 该 root 包及其所有子包所组成的 模块(module) 的名称 】
基本概念关键区别表
概念 |
定义 |
特点 |
源文件 |
.cj 文件 |
物理文件,必须声明所属包 |
包 |
编译最小单元 |
可含多个源文件,独立命名空间,独立编译 |
模块 |
包的集合 |
发布单元,可含多个包,最多一个main入口 |
包声明:每个文件必须声明package,位于文件开头(包声明必须在源文件的非空非注释的首行),由点分隔的层级结构,包名各段必须是一个仅含 ASCII 字符的合法的普通标识符,推荐用小写字母。
注意:当前 Windows 平台版本,包名暂不支持使用 Unicode 字符,包名各段必须是一个仅含 ASCII 字符的合法的普通标识符。
包由一个或多个源码文件组成,同一个包的源码文件必须在同一个目录。一个包中可以包含多个源文件。模块(module)是若干包(Package)的集合。在仓颉编程语言中,一个模块根目录下的顶层最多只能有一个作为程序入口的 main 函数。
包的导入使用import
在仓颉编程语言中,可以通过 import fullPackageName.itemName 的语法导入其他包中的一个顶层声明或定义,fullPackageName 为完整路径包名,itemName 为声明的名字。
如果要导入的多个 itemName 同属于一个 fullPackageName,可以使用 import fullPackageName.{itemName1, itemName2, …} 语法
还可以使用 import packageName.* 语法将 packageName 包中所有可见的顶层声明或定义全部导入。
导入语法
导入场景 |
语法示例 |
说明 |
导入单个声明 |
import pkg1.foo |
导入pkg1包中的foo声明 |
导入多个声明(同包) |
import pkg1.{foo, bar} |
批量导入pkg1包的foo和bar |
导入包内所有可见声明 |
import pkg1.* |
导入pkg1包中符合访问权限的所有声明 |
导入多个包的所有声明 |
import {pkg1.*, pkg2.*} |
批量导入多个包的所有可见声明 |
几点说明:
• 隐式导入:编译器自动导入core包的所有public声明(如String、Range等常用类型,无需手动导入)。
•同名标识符怎么导入使用?当不同包存在同名声明时,可通过重命名避免冲突。语法:
import 包名.声明名 as 新名 或 import 包名 as 新包名。
重命名后,当前包只能使用重命名后的新名字,原名无法使用。
• 作用域优先级:导入的声明作用域低于当前包的声明,同名声明会被 “遮盖”(函数重载除外)。
• 禁止通过 import 导入当前源文件所在包的声明或定义。
• 禁止包间的循环依赖导入,如果包之间存在循环依赖,编译器会报错。
示例
目录结构如下:
demoA ← 模块根(root)目录——工程(Project)名称
└── src ← 源码根目录(名字必须是 src)
├── main.cj ← 模块入口
├── c.cj
└── directory_0 ← 包 demoA.directory_0
├── a.cj
├── c.cj
└── directory_1 ← 包 demoA.directory_0.directory_1
└── b.cj
源文件
(1) 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()")
}
(2) 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()")
}
(3) src/directory_0/c.cj文件内容:
package demoA.directory_0 // 首行必须是 package 声明
public func helloC() {
println("demoA.directory_0 中 c.cj文件的helloC()")
}
(4) src/c.cj文件内容:
package demoA
public func helloC() {
println("demoA.directory_0 中 c.cj文件的helloC()")
}
(5) 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
相关官方文档
更多推荐
所有评论(0)