struct
SKILL.md
仓颉语言结构体 Skill
1. 结构体定义
1.1 基本语法
struct Rectangle {
let width: Int64
let height: Int64
public init(width: Int64, height: Int64) {
this.width = width
this.height = height
}
public func area() { width * height }
}
- 使用
struct关键字 + 名称 +{}体定义 - 仅可在顶层作用域定义
- 结构体体内可包含:成员变量、成员属性、静态初始化器、构造函数、成员函数
1.2 成员变量
- 实例成员变量:通过结构体实例访问。可有初始值,也可无初始值(须有类型标注)
- 静态成员变量:用
static声明,通过结构体类型名访问(非实例)
1.3 静态初始化器
static init()— 无参数,不允许访问修饰符- 须初始化所有未初始化的静态成员变量
- 每个结构体最多一个
1.4 构造函数
普通构造函数(init)
init(params) { ... }- 函数体须初始化所有未初始化的实例成员变量
- 使用
this消除参数名与成员变量名的歧义 - 多个
init构造函数仅在构成有效重载时允许
主构造函数
- 名称 = 结构体类型名。每个结构体最多一个
- 参数可以是普通参数或成员变量参数(前缀
let/var),后者同时定义成员变量和构造函数参数
struct Rectangle {
public Rectangle(let width: Int64, let height: Int64) {}
}
自动生成的无参构造函数
- 当无自定义构造函数(包括主构造函数)且所有实例成员变量有初始值时 → 编译器自动生成
public init()
1.5 成员函数
- 实例成员函数:通过实例访问。可使用
this访问实例成员变量。也可访问静态成员 - 静态成员函数(
static func):通过类型名访问。不能访问实例成员或调用实例函数 - 限制:同一个结构体中,静态方法和实例方法不能同名(即使参数不同)
1.6 成员属性(prop)
prop name: Type { get() { ... } }— 只读属性mut prop name: Type { get() { ... } set(v) { ... } }— 读写属性- 实例属性通过实例访问,静态属性(
static prop)通过类型名访问 - 属性的详细规则参见
cangjie-classSkill 第 4 节
1.7 访问修饰符
| 修饰符 | 可见性 |
|---|---|
private |
仅在结构体定义内 |
internal(默认) |
当前包及子包 |
protected |
当前模块 |
public |
全局可见 |
1.8 禁止递归结构体
- 直接和间接递归均不合法(编译错误):
struct R1 { let other: R1 } // 错误:自引用
struct R2 { let other: R3 } // 错误:相互引用
struct R3 { let other: R2 }
2. 创建结构体实例
2.1 创建
- 通过结构体类型名调用构造函数:
let r = Rectangle(10, 20) - 通过实例访问成员:
r.width、r.area()
2.2 修改实例成员须满足两个条件
- 持有实例的变量须为
var(可变) - 被修改的成员变量须声明为
var
2.3 值语义(赋值/传参时复制)
- 赋值或传递结构体实例会创建副本(浅拷贝 — 引用类型成员仅复制引用)
- 修改一个副本不影响另一个
3. mut 函数
3.1 问题
- 由于结构体是值类型,普通实例成员函数不能修改实例的成员变量
3.2 解决方案
mut函数 — 特殊的实例成员函数,可以原地修改结构体实例
struct Foo {
var i = 0
public mut func g() { i += 1 } // 合法
}
3.3 mut 允许使用的位置
- 仅在
interface、struct和结构体扩展中 - 不能用于
class(类是引用类型,实例函数本身就能修改成员)
3.4 mut 不能修饰静态函数
public mut static func g(): Unit {} // 错误
3.5 mut 也可修饰运算符函数
public mut operator func +(rhs: A): A { A() } // 合法
3.6 mut 函数中 this 的限制
this不能被 Lambda 或嵌套函数捕获this不能作为表达式使用(如返回值)- 实例成员变量不能被
mut函数内的 Lambda 捕获
3.7 接口中的 mut
- 接口函数可声明为
mut - 结构体实现接口时须精确匹配
mut修饰符(mut↔mut, 非mut↔非mut) - 类实现接口时忽略
mut(直接使用普通func) - 将结构体实例赋给接口类型变量时会复制。通过接口变量调用
mut函数修改的是副本,不影响原始结构体
3.8 mut 函数使用限制
规则 1:let 声明的结构体变量不能调用 mut 函数
let a = Foo()
a.f() // 错误:a 是 let 声明的结构体
var b = Foo()
b.f() // 正确:b 是 var
let c: I = Foo()
c.f() // 正确:c 是接口类型,非结构体类型
规则 2:结构体类型变量上的 mut 函数不能作为一等公民使用
var a = Foo()
var fn = a.f // 错误:不能将 mut 函数作为一等公民使用
var b: I = Foo()
fn = b.f // 正确:b 是接口类型
规则 3:非 mut 实例成员函数不能调用 mut 函数;mut 函数可以调用非 mut 函数
struct Foo {
var i = 0
public mut func f(): Unit {
i += 1
g() // 正确:mut 可调用非 mut
}
public func g(): Unit {
f() // 错误:非 mut 不能调用 mut
}
}
Weekly Installs
3
Repository
kong-baiming/cangjie-devFirst Seen
2 days ago
Security Audits
Installed on
opencode2
claude-code2
github-copilot2
codex2
kimi-cli2
gemini-cli2