跳到内容

类型自动转换

Crystal 在没有歧义的情况下透明地转换某些类型的元素。

数字自动转换

如果不会丢失精度,数值类型的数值会自动转换为更大的数值类型。

def foo(x : Int32) : Int32
  x
end

def bar(x : Float32) : Float32
  x
end

def bar64(x : Float64) : Float64
  x
end

foo 0xFFFF_u16 # OK, an UInt16 always fit an Int32
foo 0xFFFF_u64 # OK, this particular UInt64 fit in an Int32
bar(foo 1)     # Fails, casting an Int32 to a Float32 might lose precision
bar64(bar 1)   # OK, a Float32 can be autocasted to a Float64

即使数字字面量的类型不同,只要字面量的实际值适合目标类型,数字字面量也会被始终转换。

表达式会被转换(就像上面的最后一个示例一样),除非将标志 `no_number_autocast` 传递给编译器(请参阅 编译器特性)。

如果存在歧义,例如,因为存在多个选项,编译器会抛出错误。

def foo(x : Int64)
  x
end

def foo(x : Int128)
  x
end

foo 1_i32 # Error: ambiguous call, implicit cast of Int32 matches all of Int64, Int128

目前,自动转换仅在两种情况下起作用:在函数调用时(如前面所示)以及在类/实例变量初始化时。以下示例展示了实例变量的两种情况:在初始化时进行转换有效,但在赋值时则无效。

class Foo
  @x : Int64 = 10 # OK, 10 fits in an Int64

  def set_x(y)
    @x = y
  end
end

Foo.new.set_x 1 # Error: "at line 5: instance variable '@x' of Foo must be Int64, not Int32"

符号自动转换

符号会自动转换为枚举成员,从而能够更简洁地编写它们。

enum TwoValues
  A
  B
end

def foo(v : TwoValues)
  case v
  in TwoValues::A
    p "A"
  in TwoValues::B
    p "B"
  end
end

foo :a # autocasted to TwoValues::A