オブジェクト指向プログラミングとは、プログラムをオブジェクトで構成し、そのオブジェクト間でメッセージのやりとりをすることで処理を作っていくプログラミング手法です。
クラスとはデータとデータへの操作の定義であり、オブジェクトの設計図となるものです。
多くのOOP言語で、OOPを実現する手段とされている。(ちなみに、この手の言語をクラスベースという。 他にはプロトタイプベースというスタイルのOOPもある。)
では、さっそく、F#のクラスについての説明に移りましょう
次のサンプルは、モンスターを表すクラスを定義し、そのモンスタークラスのオブジェクトを生成、そして、そのオブジェクトのメソッドをコールしています。
#light type Monster(level:int,hp:int) = class member x.Level = level; member x.Hp = hp; member x.ShowStatus = printfn "level=%d, hp=%d" level hp end let x = new Monster( 10, 200 ) x.ShowStatus
level=10, hp=200
オブジェクト指向の多態性(ポリモーフィズム)を実現するための仕組みとして、アップキャスト、ダウンキャストがあります。
派生クラスから基底クラスへのキャスト
キーワード:>を使って以下の構文でアップキャストできます
派生クラスのオブジェクト :> 基底クラスの型
以下に示すサンプルは、すべての型がSystem.Object (F#ではobjと省略できる)から派生していることから、 string型をobj型にアップキャストしてみる
■サンプル
> let a = "abcdefg" :> obj;; val a : obj
基底クラスから派生クラスへの変換
キーワード:?>を使って以下の構文でダウンキャストできます
基底クラスのオブジェクト :?> 派生クラスの型
■サンプル
> let b = a :?> string;; val b : string
ちなみに、不正なダウンキャストを行うとSystem.InvalidCastException が発生します
■サンプル
> let b = a :?> int;; val b : int System.InvalidCastException: 指定されたキャストは有効ではありません。 場所.$FSI_0009._main()
プロパティはフィールドのように扱うことができるアクセサです。
プロパティがなければ、Set, Getメソッドをフィールドごとに用意しなければならず、クラス定義がとても繁雑になってしまうでしょう。
プロパティを理解ために、円を表すクラスを定義してみます
■サンプル
type Circle(radius:float) = let PI = 3.14 let mutable r = radius member this.Radius with get () = r and set radius = r <- radius member this.Area with get () = r * r * PI and set area = r <- sqrt( area / PI )
定義したクラスを使ってみる。
> let circle = new Circle( 2.0 );; val circle : Circle > circle.Radius;; val it : float = 2.0 > circle.Area;; val it : float = 12.56 // 半径を変更する > circle.Radius <- 4.0;; val it : unit = () > circle.Radius;; val it : float = 4.0 > circle.Area;; val it : float = 50.24 // 面積を変更する > circle.Area <- 20.0;; val it : unit = () > circle.Radius;; val it : float = 2.523772326