カプセル化

オブジェクト指向の利点の一つにカプセル化があります。 カプセル化とは、オブジェクトの内部のデータや振る舞いを隠蔽し 不必要な情報を外部に公開しないようにすることです。 例えばテレビを見るとき、利用者はリモコンの使い方がわかればよく テレビの動作原理について知る必要はないですよね。 そういう内部の動作原理は隠してしまって(カプセル化) 外部へは、インタフェースだけを公開する(テレビでのインタフェースはリモコン) というのがカプセル化の考え方です。 この節では、カプセル化のための機能の一つとして Accessibility Annotationを説明します。 例として、パックマンのような格子状の盤面を動くゲームを考えます。 ここで、前回紹介したPoint型を使っていた場合 2点の距離を表す関数distanceを追加したいと思うかもしれません。 例えばこんな感じ
距離を定義したPointクラス
type Point = {mutable x : int; mutable y : int}
    with
        member v.abs (x:int) =
            if x>=0 then x else -x
        member v.distance (p:Point) =
            abs(p.x - v.x) + abs(p.y - v.y);
    end;;
この例ではdistanceを実装するのに 補助関数としてabsを定義しています。 しかし、この状態でPoint型を公開したとすると 本来使ってもらおうと思って公開しているわけではない abs関数も使用されてしまう可能性があります。
ユーザによる想定外の使われ方
Console.WriteLine (p.abs 10);;    
後になって、ユークリッド距離を使うように変更するため absを削除して別の処理を書こうと思ったとします。 しかし、既に誰かがabsメソッドを使っているかもしれないため 使わなくなってしまったabsメンバを 不用意に削除することが出来なくなります。 このような場合に備えて、Accessibility Annotationを使って 公開したくないクラスにアクセス制限をかけることが出来ます。 Accessibility Annotationには次の3つがあります。  ・public 全てグローバルに公開する ほとんどのデータ型のデフォルト  ・internal アセンブリ内に公開(DLLまたはEXE内)  ・private 型定義またはモジュール内で公開 これを用いるた例が以下のプログラムです。
アクセス制御
open System;;
type Point = {mutable x : int; mutable y : int}
    with
        member private v.abs (x:int) =
            if x>=0 then x else -x
        member v.distance (p:Point) =
            abs(p.x - v.x) + abs(p.y - v.y);
    end;;
let p = {x=10;y=10} in
let q = {x=20;y=20} in
Console.WriteLine (p.distance q);   //OK
Console.WriteLine (p.abs 10);;      //エラー
absメソッドの前にくっついているprivateキーワードによって Point型の定義の外からはabsメソッドにアクセスできないようになります。 このAccessibility AnnotationはF#のほとんどの場所で使用することが出来、 使用できる場所としては以下のものがあります。  ・上記のようなmember定義(後述するクラス、構造体でも同様)  ・new(..)オブジェクトコンストラクタ定義  ・モジュール定義内のlet,module,type,extern宣言と   パターンの個別の識別子 自分だけが使うようなプログラムならそこまで気にする必要はないかもしれませんが 外部に公開するライブラリを書きたいというケースでは 是非、気をつけたい所です。