クラスの概要
クラス(= class)は、プロパティやメソッド、イベントなどのメンバを持つことができるオブジェクト型です。クラスはオブジェクト指向プログラミング(= OOP)の世界の概念です。通常、関数型プログラミングにはクラスの概念はありませんが、オブジェクト指向と関数型プログラミングとを組み合わせた OCaml から進化した F# には最初から備わっている機能です。
クラスは主に .NETプログラミング をする際に非常に役に立ちます。それは、基本的に.NETの世界はオブジェクト指向で形成されているためです。F#単体で開発する場合は、あまり必要とならないケースが多いですが、C# / VB.NETなどとやりとりする場合や、そもそも .NET の機能を利用する場合はクラスを必ず利用するため、クラスの概念を学ぶことはほぼ必須と言っても過言ではないでしょう。
この項では、クラスの概要レベルの内容についてご紹介します。詳細な内容については、別途項目を用意しているので、そちらをご参照ください。
以下はクラスの簡略化した構文になります。
// ------------------
// [ 構文 ]
// ------------------
type class-name ( parameter-list ) = [ class ]
[ let-bindings ]
[ do-bindings ]
member-list
...
[ end ]
継承やインターフェース実装を考慮せず、オプションの機能を省くと上記のようなシンプルな構造であることがわかります。前述したとおり、詳細な記述方法に関しましては別途記事を用意いたしますので、ここではクラスの基本的な機能について入門するようにしてください。
冗語構文と軽量構文
各要素の説明については次節で紹介しますので、今回は PersonBクラス の class - end の部分に注目していきます。これは 冗語構文 と呼ばれる記述方法です。通常は Personクラス のような方法(= 軽量構文)で記述をします。冗語構文はあまり利用されない記述方法ですが、インデントによる影響を受けにくくなるという利点があります。また、class / struct / interface を明示的に表す際にも有効です。これら3種類の型は属性によっても明示的に分類することが可能ですが、冗語構文を利用した方が見た目に美しいコードになりやすいです。また、反対に軽量構文で統一しても問題ありません。いずれにせよ、どちらか片方(= 冗語構文 or 軽量構文)に統一した方がよいと思います。
余談ですが、あえて軽量構文のデメリットを言うならば、F#にあまり明るくない人が見たときに、それが class なのか struct なのか interface なのか一見しただけではわかりにくいというところです。誰がみてもわかりやすいコードというものが良いコードだと私は考えていますので、class / struct / interface の宣言においては冗語構文を採用するか、属性を必ず記述する方がいいと思います。
サンプルでみるクラス
前節でクラスの簡単な構文を紹介しました。本節では簡易的なサンプルを利用して、実際の値と構文の説明がどう対応しているかを見ていきたいと思います。今回のサンプルは前節と同様の Person型 を利用していきたいと思います。
繰り返しとなりますが、下記は Person型 の定義となります。
下記の表は内包している要素と構文の要素名とを対応付けたものとなります。ただし重複する内容のものに関しては省略しています。
また、改めてクラスの宣言構文も記載しています。
// ------------------
// [ 構文 ]
// ------------------
type class-name ( parameter-list ) = [ class ]
[ let-bindings ]
[ do-bindings ]
member-list
...
[ end ]
要素名 | 対応するPerson型の要素 |
---|---|
class-name | Person |
parameter-list | (name, age) |
let-bindings | let name = name let age = age |
do-bindings | printfn "Person intput: name= %s, age= %d" name age |
member-list | this.Name this.Age |
クラスの構成はやや複雑です。最初に [ class-name ] を指定し、その後 [ parameter-list ] を指定していることはすぐにわかると思います。[ parameter-list ] は tuple型 で受け取ることになるので覚えておきましょう。そのあと [ let-bindings ] と [ do-bindings ] が宣言されています。この箇所はクラス型の値を作成するときに必ず最初に実行されます。この [ parameter-list ] と [ let-bindings ] と [ do-bindings ] を 合わせて、コンストラクタ といいます。また、クラス型の値を作成することを インスタンス化 といいます。頻出する単語なので必ず覚えましょう。new (parameter-list) を使うことで追加のコンストラクタを定義することも可能です。
[ let-bindings ] の値を ローカルフィールド または privateメンバ などと呼びます。これは基本的に公開範囲が private であり、クラスの外部に公開されないために、そう呼ばれています。それとは逆に、[ member-list ] を利用することで、クラス外に公開するプロパティやメンバメソッドを定義することが可能です。[ member-list ] は [ let-bindings ] とは違い、デフォルトの公開範囲が public に設定されています。
クラスは非常に多機能な型です。また、クラスはオブジェクト指向プログラミングの世界の概念なため、関数型プログラミングに慣れ親しんだ方からすると理解することが難しいかもしれません。しかし、.NETプログラミングをする上では切っても切れない機能であるため、しっかりと使えるようにしましょう。