型別自動轉換¶
當不存在歧義時,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