コンテンツへスキップ

型自動キャスト

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

現時点では、自動キャストは、これまで示した関数呼び出し時と、クラス/インスタンス変数の初期化時の2つのシナリオでのみ機能します。次の例は、インスタンス変数に対する2つの状況を示しています。初期化時のキャストは機能しますが、代入時のキャストは機能しません。

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