Obj型
F#には、全てのクラスにとっての親クラスにあたる
obj型という型が存在し、
obj型は、.Net FrameworkのSystem.Object型の省略形になります。
親クラスは、子クラスの機能を全て持っているため
全ての型は安全にobj型に変換(コアーション)することが出来ます。
- コアーションとそれに類した操作
- :>とupcast //static coercion expression(F# 4.1 spec 6.7.2)
:? //dynamic type-test expression(F# 4.1 spec 6.7.3)
:?>とdowncast //dynamic coercion expression(F# 4.1 spec 6.7.4)
ある型をその親クラスの型に変換することを、アップキャスト(upcast)と言い
ある型をその子クラスの型に変換することを、ダウンキャスト(downcast)と言います。
一般的に、
アップキャストは安全(大は小を兼ねる)で
ダウンキャストは危険(小は大を兼ねないので)だと言われます
普通の数値型なども
obj型に安全にアップキャストすることが出来ます。
obj型へのアップキャスト
> let a = 1 :> obj;;
val a : obj = 1
> let b = (upcast 1 : obj);;
val b : obj = 1
> let c = "abc" :> obj;;
val c : obj = "abc"
> let d = (upcast "abc" : obj);;
val d : obj = "abc"
obj型へのコア-ションは
box演算子(box operator F# 4.1 spec 18.2.6)によっても実現できます。
これは、渡されたものをオブジェクト表現(object representation)に変換する演算子です。
box演算子
> let a = box 1;;
val a : obj
> let b = box "abc";;
val b : obj
また、これとは逆の演算子としてunbox演算子(unbox operator F# 4.1 spec 18.2.6)があります
これは、互換性のない型に戻すと例外が発生してしまうため
気をつけて使用しなければなりません。
unbox演算子
> let a = box 1;;
val a : obj = 1
> let b = unbox<int> a;;
val b : int = 1
> let c = unbox<string> a;;
System.InvalidCastException: 型 'System.Int32' のオブジェクトを型 'System.String
' にキャストできません。
場所 <StartupCode$FSI_0013>.$FSI_0013.main@()
Stopped due to error
そのため、通常は:?(Dynamic Type-Test Expressions)を用いて
変換が出来るかを判定してからダウンキャストを行います
Dynamic Type-Test Expressionsの利用
let a = box 1 in
let b = box "abc" in
let check (x:obj) =
match x with
| :? int -> System.Console.WriteLine "int"
| :? string -> System.Console.WriteLine "string"
| _ -> System.Console.WriteLine "other type" in
check a;check b;;
Dynamic Type-Test Expressionsは関数のようにもつかえます。
( obj :? type )のように使用すると、objがtypeに変換可能なときはtrue
それ以外ならfalseを返します
Dynamic Type-Test Expressionsの利用その2
> let a = box 1 in if (a :? int) then true else false;;
val it : bool = true
boxやunboxはオブジェクト変換演算子(Object Transformation Operators)と呼ばれ
この仲間としては
基礎編で出てきたrefと!の他、
hash/sizeof/typedefofを合わせて全8種類あります。
最後に、F#の基本的な型がどういう親クラスを持つかについては
付録にまとめてあります。