Skip to Content

标志位(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 16

Set 加位、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 20

A、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 1

aliasF 从 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日