Skip to Content

类型转换

MushScript 中,有多种类型转换的方法。

T(v):数值转换与解析

转换写成「类型名当函数」的调用形式,按源与目标的类型自动分派语义。数值转换永不失败,浮点转整数向零截断(不是四舍五入):

val trunc = int64(3.9); print(trunc);
3
  • 整数类型不收小数字面量,连 3.0 也不收(val w: int = 3.0;)。
  • 浮点常量转窄整数时编译期查值域:int16(-40000.0f64) 报 MS4211。
  • char 的互转走码点中转:int('A') 取码点,char(66) 按码点构字符。

字符串源进解析通道:int("42") 得 42,bool("True")、decimal64("1.5") 同理。解析失败会抛 System.ConversionError,避错可用 try?(失败得 null):

print(try? int("42")); print(try? int("x")); print(try? bool("True"));
42 null True
Note

bool / string 目标位只收字符串源。

用户转换:顶层 conversion

用户转换声明在模块顶层,类型体与扩展体内不再有转换声明(写在那里会定向报错并提示迁移到顶层)。

转换恒单参、返回类型必声明:conversion 是显式形,仅经 T(v) 消费。implicit conversion 在隐式位(赋值、传参、返回、操作数位)自动生效,同样可以被 T(v) 显式调用,但声明为 implicit 时不能再与 fail 组合。

class Meters { public var v: int = 0; } public conversion(v: int) -> Meters { return new Meters() { v: v }; } public implicit conversion(m: Meters) -> int { return m.v; } func main() -> int { val m = Meters(42); val n: int = m; print(m.v, n, int(m), m + 1); return 0; }
42 42 42 43

跨模块激活经 import 门控:import moduleA; 即激活其声明的转换,未导入不可见;两个已导入模块声明了同一对转换时,使用点会报歧义错误。

从字符串解析用户类型,标准写法就是一个源为 string 的 fail conversion,失败走 fail 通道,T(v) 调用点须 try/capture 消费:

struct Celsius { public val C: float; public init(c: float) { C = c; } } public conversion(s: string) fail System.ConversionError -> Celsius { return new Celsius(try float(s)); } func main() -> int { val c = try? Celsius("36.5"); print(c != null); if c != null { print(c.C); } return 0; }
True 36.5

is、as 与受检转 T(v)

该使用哪一种转换方式,可以看下方的表格:

写法返回失败行为
is TboolFalse
as TT?null
T(v) 受检转裸 Tfail System.ConversionError,须消费

数值标量之间 as 返回裸 T:

val viaAs = 3.9 as int64; print(viaAs);
3

编译期按两侧类型的关系分级:派生到基、实现者到协议位、同型,恒成功零开销,向下转与 any 源留给运行期检查。

两个类型没有基类链也没有协议实现相连时,T(v) 编译期直接拒绝。as 对无关引用类型不拒绝,运行期得 null,对跨域目标(比如把自定义类型 as 到数值)编译期报 MS3241。受检转的结果保证是有效实例,不参与判空。

class Animal { public func Name() -> string { return "animal"; } } class Dog : Animal { public func Bark() { print("woof"); } } func Describe(a: Animal) -> int { val soft = a as Dog; print(soft == null); val hard = try? Dog(a); print(hard != null); return 0; } func main() -> int { Describe(new Dog()); Describe(new Animal()); return 0; }
False True True False

any 源的转型走运行期检查,协议位同样按实现链判定:

val o: any = new Dog(); print(o is Dog); val d = o as Dog; print(d == null);
True False

当声明了(源 -> 目标)转换方法时,T(v) 走转换通道,不做引用检查。

注意

  • 同家族整数之间的转换同样用调用形式(如 int8(x))。
  • 显式转换在编译期检查目标类型是否存在,拼错类型名会当场报错。
最后更新于 2026年10月9日