Vala编程语言教程-数据类型
核心数据类型
Vala 的数据类型分为两大类别:
类型 | 行为特性 |
---|---|
值类型 | 赋值时创建副本(如 int , struct ) |
引用类型 | 赋值时共享对象,新标识符指向同一内存(如 class , string ) |
常量定义使用 const
修饰符,命名规范为全大写加下划线:
const double MU_BOHR = 927.400915E-26;
值类型
Vala 支持以下基础值类型:
类别 | 类型示例 |
---|---|
字节类型 | char (历史遗留名,实际为字节), uchar |
Unicode字符 | unichar (32位) |
整数类型 | int , uint , long , ulong , short , ushort |
定长整数 | int8 , uint16 , int32 , uint64 等(数字代表位数) |
浮点数 | float , double |
布尔值 | bool (仅 true /false ) |
结构体 | struct 自定义复合类型 |
枚举 | enum (底层为整数值,非类形式) |
示例代码:
unichar c = 'ü'; // Unicode 字符
float percentile = 0.75f; // 单精度浮点数
struct Vector { // 三维向量结构体
public double x;
}
enum WindowType { TOPLEVEL, POPUP } // 窗口类型枚举
类型操作:
ulong size = sizeof(int32); // 获取类型字节数(int32 为 4 字节)
int max_val = int.MAX; // 获取 int 最大值(2147483647)
字符串(引用类型)
核心特性:
- 编码:UTF-8,不可变(Immutable)
- 声明方式:
string text = "标准字符串"; // 支持转义符如 \n, \t string raw_str = """ // 原始字符串(保留格式,不转义) 多行文本,可直接包含 "引号", 换行和缩进均保留。 """;
字符串模板:
int a = 6, b = 7;
string expr = @"$a × $b = $(a * b)"; // 输出 "6 × 7 = 42"
操作与方法:
操作 | 示例 | 结果 |
---|---|---|
切片 | "hello"[1:4] | "ell" |
包含判断 | if ("ere" in "Able was I...") | 返回 true |
类型转换 | int.parse("42") → 42 | 字符串转数值 |
控制台交互 | stdout.printf("%s", str) | 格式化输出 |
string input = stdin.read_line() | 读取用户输入 |
索引访问(Vala ≥0.11):
uint8 byte = text[3]; // 获取第3个字节(索引从0开始)
String与其他类型间的相互转换:
bool b = bool.parse("false"); // => false
int i = int.parse("-52"); // => -52
double d = double.parse("6.67428E-11"); // => 6.67428E-11
string s1 = true.to_string(); // => "true"
string s2 = 21.to_string(); // => "21"
判断是否是字符串的子串:
if ("ere" in "Able was I ere I saw Elba.") ...
数组
声明与初始化:
int[] a = new int[10];
int[] b = { 2, 4, 6, 8 };
切片操作:
int[] c = b[1:3]; // => { 4, 6 }
核心属性:
特性 | 说明 |
---|---|
长度获取 | int len = arr.length |
动态扩容 | arr.resize(15) |
值类型数组 | 存储实际数据(如 int[] 每个元素独立) |
引用类型数组 | 存储对象指针(如 string[] 共享对象) |
内存特性:
- 数组在内存中连续存储,可通过指针操作高效访问。
- 多维数组以行优先(Row-major)顺序存储。
创建多维数组:
int[,] c = new int[3,4];
int[,] d = {{2, 4, 6, 8},
{3, 5, 7, 9},
{1, 3, 5, 7}};
d[2,3] = 42;
多维数组各维度大小:
int[,] arr = new int[4,5];
int r = arr.length[0]; // => 4 第一维的长度
int c = arr.length[1]; // => 5 第二维的长度
与其他语言的区别:
不支持[][]和切片操作:
int[,] arr = {{1,2},
{3,4}};
int i = arr[0,1]; // work a = 1
int j = arr[0][1]; // won't work
int[] b = arr[0]; // won't work
int[] c = arr[0,]; // won't work
int[] d = arr[:,0]; // won't work
int[] e = arr[0:1,0]; // won't work
int[,] f = arr[0:1,0:1]; // won't work
动态扩容:
Vala 允许使用 +=
操作符实现数组的动态扩容,但需遵循以下规则:
int[] arr = {1, 2, 3};
arr += 4; // 合法:局部数组 → 变为 [1,2,3,4]
arr += 5,6; // 批量追加 → [1,2,3,4,5,6]
move方法:
Vala 提供 move(src, dest, length)
方法实现数组元素块移动,具体行为如下:
int[] arr = {1, 2, 3, 4, 5};
// 将索引 1 开始的 2 个元素移动到索引 3 处
arr.move(1, 3, 2);
// 原位置 1-2 被填充 0 → [1, 0, 0, 2, 3]
引用类型
所有声明为类的类型均为引用类型,无论它们是否继承自 GLib 的 Object。Vala 会确保当以引用方式传递对象时,系统将跟踪当前存活的引用数量以自动管理内存。未指向任何对象的引用值为 null
。这一点与java类似。
/* 定义一个类 */
class Track : GLib.Object { /* 继承自'GLib.Object' */
public double mass; /* pbulic 字段 */
public double name { get; set; } /* public 属性 */
private bool terminated = false; /* 私有字段 */
public void terminate() { /* 公共方法 */
terminated = true;
}
}
类型转换
Vala支持以下方式的类型转换,适用于所有vala数据类型:
int i = 10;
float j = (float) i;
类型推断
Vala 有一种称为类型推断的机制,只要使用var关键字而不是给出具体类型来定义局部变量。类型是从赋值的右侧推断出来的。它有助于减少代码中不必要的冗余,而不会牺牲静态类型特性:
var p = new Person(); // same as: Person p = new Person();
var s = "hello"; // same as: string s = "hello";
var l = new List<int>(); // same as: List<int> l = new List<int>();
var i = 10; // same as: int i = 10;
而且类型推断对于具有泛型类型参数的类型特别有用:
MyFoo<string, MyBar<string, int>> foo = new MyFoo<string, MyBar<string, int>>();
// 可以使用以下方式定义foo
var foo = new MyFoo<string, MyBar<string, int>>();
从其他类型定义新类型
/* 给一个基础类型int定义一个别名Integer (等同于C语言中的 typedef int Integer)*/
[SimpleType]
public struct Integer : uint {
}
/* 给GLib.List<GLib.Value>定义别名: ValueList */
public class ValueList : GLib.List<GLib.Value> {
[CCode (has_construct_function = false)]
protected ValueList ();
public static GLib.Type get_type ();
}