结构体
概述
Wave语言的结构体是用于声明用户自定义数据类型的核心语法元素。 使用结构体可以将不同类型的值组合成一个逻辑单元,从而可以明确和安全地建模复杂的数据结构。
Wave的结构体以值类型(value type)运作。 所有字段必须具有明确的类型,创建结构体实例时,所有字段都必须初始化。 这些规则确保结构体的状态始终保持完整和可预测。
结构体声明语法
结构体使用 struct 关键词来声明。
结构体的名称使用帕斯卡命名法(PascalCase),结构体正文中可以定义一个或多个字段。
字段以 名称: 类型; 的格式声明,每个字段声明后必须有分号。
struct Box {
size: i32;
weight: f32;
}
结构体声明时,字段的编写顺序与内存布局顺序相同。 结构体内部只允许字段声明,不可以包含函数或方法。 操作逻辑在结构体外部单独定义。
结构体创建语法
结构体以使用结构体名称的字面量形式创建。
结构体字面量是 StructName { 字段名: 值; ... 以 }` 的形式编写。
var b: Box = Box {
size: 42;
weight: 10.5;
};
创建结构体时必须初始化定义的所有字段, 如果有一个字段缺失,将会发生编译错误。
初始化时,字段的编写顺序无需与结构体声明顺序一致, 但传递给每个字段的值的类型必须与结构体中定义的类型完全匹配。 在Wave中,结构体字段初始化过程中不允许隐式类型转换。
结构体字段访问语法
结构体的字段通过点标记法访问。 字段访问在读取和写入时使用相同的语法。
println("Size: {}", b.size);
println("Weight: {}", b.weight);
尝试使用不存在的字段名称将导致编译阶段发生错误。 由于结构体是值类型,将整个结构体赋值或作为函数参数传递时, 包含在结构体中的所有字段都会被一起复制。
结构体方法定义语法
Wave语言不在结构体内部直接定义方法。
相反,通过使用 proto 关键词声明与结构体关联的方法集合。
proto 块是属于特定结构体的函数域,
在此块中定义的函数用作该结构体的方法。
方法使用第一个参数 self 来传递结构体实例。
self 代表结构体的全部值,以值复制方式传递。
proto Box {
fun print(self) {
println("size={}, weight={}", self.size, self.weight);
}
fun added_size(self, x: i32) -> i32 {
return self.size + x;
}
}
proto 块不需要与结构体声明位于同一文件中,
可通过多个 proto 块来分散定义同一结构体的方法。
方法调用使用点标记法,且以与常规函数调用相同的方式运作。
b.print();
var n: i32 = b.added_size(5);
作为函数参数的结构体使用
结构体作为函数参数传递时,以值复制方式处理。 即使在函数内部修改结构体的字段,也不会影响调用方的结构体实例。
fun calc(box: Box) -> i32 {
return box.size * 2;
}
结构体用作函数返回值时,也发生同样的值复制。 这种行为确保了结构体的不变性和可预测的数据流。
嵌套结构体 (Nested Struct)
在Wave中,可以使用其他结构体作为结构体的字段类型。 因为结构体是完整的类型,所以可以自由嵌套。
struct Position {
x: i32;
y: i32;
}
struct Player {
name: str;
pos: Position;
}
嵌套结构体的字段通过连续使用点标记来访问。
var p: Player = Player {
name: "Alice";
pos: Position { x: 10; y: 20; };
};
println("玩家 X: {}", p.pos.x);
println("玩家 Y: {}", p.pos.y);
可以在结构体字面量内部嵌套其他结构体字面量, 在这种情况下,所有字段的初始化规则依然适用。
结构体数组
结构体可以用作数组的元素类型。
Wave的数组语法是使用array<类型, 长度>格式,也可以指定结构体类型。
var players: array<Player, 3> = [
Player { name: "A"; pos: Position { x: 1; y: 2; }; },
Player { name: "B"; pos: Position { x: 3; y: 4; }; },
Player { name: "C"; pos: Position { x: 5; y: 6; }; }
];
访问结构体数组的元素时,先使用数组索引, 再通过点标记法访问结构体内部字段。
println("第二位玩家 X: {}", players[1].pos.x);
结构体基本操作可能性
Wave的结构体是用户自定义类型, 因此不会自动参与算术运算或比较运算。
如果需要进行结构体的等同性比较、排序、哈希、数值运算等操作,
必须通过proto块明确地定义这些行为。
Wave不为结构体提供隐式运算符,
所有操作都必须以明确的方式定义为原则。