标志位(Flags)
flags 声明可按位组合的常量集合。成员物理上是 int 位,但同声明的组合运算保持 flags 静态面,方法面直接可用。
声明与组合
flags Perm
{
Read,
Write,
Execute = 16,
}
val p = Perm.Read | Perm.Write;
print(p);
print(p.Has(Perm.Read), p.Has(Perm.Execute));3
True False无值成员按 2 的幂自动递增(首成员 1,其后逐成员乘 2),显式值之后的隐式成员从「前一显式值乘 2」起步。| 组合同声明成员得到 flags 静态面,Has(成员) 判断是否包含。
Set、Clear、Toggle
三个方法都返回新的 flags 值,原值不动:
val full = p.Set(Perm.Execute);
print(full.Has(Perm.Execute), p.Has(Perm.Execute));
val less = full.Clear(Perm.Write);
print(less, less.Toggle(Perm.Read));True False
17 16Set 加位、Clear 去位、Toggle 翻转。less 是 Read | Execute(1 + 16)输出 17,再翻转 Read 剩 16。
与 int 互转
flags 物理上是 int 位,两个方向都隐式转换:
val n: int = p;
print(n);
val q: Perm = 3;
print(q, q.Has(Perm.Read | Perm.Write));3
3 True从 int 来的 flags 照样有完整方法面。跨 flags 类型的位运算按 int 位运算处理,结果不再保有 flags 面。
隐式递增的精确规则
无值成员按 2 的幂递增;显式值之后,隐式成员从「前一显式值乘 2」继续:
flags Mode
{
A,
B,
C = 10,
D,
}
print(Mode.A, Mode.B, Mode.C, Mode.D);1 2 10 20A、B 走 1、2,C 显式定为 10,D 从 20 起步。成员值必须编译期整型常量,重复值是合法的别名语义(两个名字同一位)。
别名与跨类型
int 到 flags 隐式转换,转换结果保有完整方法面,两个不同 flags 类型的位运算按 int 退化,结果不再保有 flags 面:
flags Other
{
X,
}
val aliasF: Mode = 1;
print(aliasF.Has(Mode.A), aliasF.Has(Mode.B));
val cross = Mode.A | Other.X;
print(cross);True False
1aliasF 从 int 1 构造,与 Mode.A 等价:Has(Mode.A) 成立,Has(Mode.B) 不成立。cross 已经是普通 int,需要 flags 面就要显式注解回 Mode。
注意
- 打印 flags 会直接输出数值,需要名字需要自己按位拆解。
Has接组合位(q.Has(Perm.Read | Perm.Write)判断「两位都有」)。- 位运算
& | ^ ~ << >>全部可用,语义就是 int 位运算。 Set/Clear/Toggle都是值语义,返回新 flags,常用于链式配置。
最后更新于 2026年10月9日
