a wandering wolf

Does a wandering wolf dreams of a wondering, sometimes programming sheep?

このエントリーをはてなブックマークに追加

クラス定義でのアクセス修飾子

基礎的なところがよく分かってなかったので、自分のためにメモ。

話の中身

// Class definition:
type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] =
   [ class ]
     [ inherit base-type-name(base-constructor-args) ]
     [ let-bindings ]
     [ do-bindings ]
     member-list
      ...
   [ end ]
// Mutually recursive class definitions:
type [access-modifier] type-name1 ...
and [access-modifier] type-name2 ...
...

(クラス (F#) - MSDN より)

これは F# におけるクラスの定義なんですが、”Class definition” のところをよーく見ると、 access-modifiertype キーワードの後と parameter-list の前にそれぞれあることに気づきます。

前者は

type internal AssemblyInnerClass(someCode: int) = ...

という定義で、このクラスに対するアクセシビリティを設定するものです。

後者は

type CannotInitializeDirectoryClass private(secretCode: int) = ...

ということになりますが、これが何をしているものかよく知りませんでした。

先述した MSDN Library の記述をよく読んでみると、どうやら後者の定義はプライマリ・コンストラクタに対するアクセシビリティの設定を行うようです。

type NonsenseClass private(caller: string) =
    let _caller = caller
    new() = NonsenseClass("from 0-args constructor")
    static member create() = NonsenseClass("from create method")
    member self.WhoCalled = _caller

こういう風にクラスを定義すると、

> let nc1 = NonsenseClass("from primary constructor");;

  let nc1 = NonsenseClass("from primary constractor");;
  ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

stdin(6, 11): error FS0501: The member or object constructor 'NonsenseClass' takes 0 argument(s) but is here given 1. The required signature is 'new : unit -> NonsenseClass'.

> let nc2 = NonsenseClass();;

val nc2 : NonsenseClass

> let nc3 = NonsenseClass.create();;

val nc3 : NonsenseClass

> nc2.WhoCalled;;
val it : string = "from 0-args constructor"
> nc3.WhoCalled;;
val it : string = "from create method"
>

という具合に動作します。プライマリ・コンストラクタを使おうとすると、「1引数を取るコンストラクタが見つからないよ!」と言われますね。

という訳で

お勉強になったかな? > @自分