Cotton Bolls: オブジェクト生成のUniform Access
« コンテンツ言語Curl | トップページ | 開発環境としてのMake »
2004.02.15
オブジェクト生成のUniform Access
人を表すクラス:Personがプロパティ:age(年齢)を持つとしよう.このとき,ageにアクセスするメソッドの実装は,毎回誕生日から計算する方法と,年齢を保持するフィールド:ageの値をそのまま返す方法などが考えられる.どちらを選ぶかはPersonクラスの実装者に委ねられており,ageプロパティの実装によってアクセス方法が変わるようなことがあれば,Personクラスのモジュール性は著しく悪くなる.つまり,オブジェクトのプロパティは,実装によらず同じようにアクセスできること――これがBertrand MeyerのUniform Access Principleだ.
Uniform Accessの観点から,Javaはあまりいい言語とは言えない.プロパティごとにgetter, setterメソッドを作る必要があるからだ.一方Curlでは,その辺りはきちんとサポートされている.先ほどのPersonクラスは,フィールドを使って次のように実装できる:
{define-class Person field public-get private-set age:int ... }
上の例では,int型のageフィールドを宣言し,アクセス修飾子としてpublic-get, private-setを使っている.こうするとageは読み取り専用フィールドとなる.get, setごとにアクセス指定できるのが面白いところだ.このとき,Person.ageプロパティのアクセス方法は次のようになる.
{value let person = {Person} person.age }
変数:personにPersonクラスのインスタンスがセットされ,person.ageが評価されてブラウザに年齢が表示される.
次に年齢を誕生日からの計算で求めたくなったとしよう.このときgetter宣言をすればUniform Accessを壊さないageプロパティの実装が可能だ:
{define-class Person {getter public {age}:int || ここで年齢を計算 } }
このように,Curlではgetter宣言をすることでUniform Accessを壊さず実装できる.なお,同じようにsetter宣言があることを補足しておこう.
さて,ここまではVisual BasicやDelphiなどにも実装されており,特筆すべきことはない.Curlが優れているのは,Uniform Accessをオブジェクト生成にまで拡張していることにある――つまり,ファクトリーと呼ばれる機能だ.
一般に,クラスの利用者がインスタンスを取得するには次の2つの方法があるだろう:
- コンストラクタを直接利用する
- ファクトリーメソッドを利用する
この機能は,上のどちらの場合でもアクセス方法を同じにできる,という仕組みだ.つまり,呼び出し側はオブジェクト生成がコンストラクタによるものなのか,ファクトリーメソッドによるものなのかを気にしなくてよい.ファクトリーを使えば,オブジェクトの生成方法を自由にオーバーライドできる.そういう意味でこれは画期的な機能だ.
ファクトリー自体は通常のファクトリーメソッドの作り方と同じだ.そのクラスまたはサブクラスとなるオブジェクトを生成し,適当な初期化を行った後でそのオブジェクトを返せばよい.例えばSingletonパターンをファクトリーで実装すると次のようになる:
{define-class Singleton let instance:Singleton = {Singleton.create} {constructor private {create} } {factory {default}:Singleton {return Singleton.instance} } }
上のコードで,instanceはSingletonオブジェクトを保持するクラス変数だ.createという名前のprivateなコンストラクタを使ってこれを初期化する.次のfactory宣言の本体では,もっぱらこのinstanceを返しているだけだ.こうすることで,次のコード:
{value let s1 = {Singleton} let s2 = {Singleton} s1 == s2 }
はtrueと表示される.一見Singletonオブジェクトを2つ作っているように見えるが,実はs1, s2は同じオブジェクトを参照しているのだ.
さて,オブジェクト指向でよく問題になるのが,オブジェクトを生成する側のコードに具象クラスのクラス名を書かなければならない,ということだ.GoFのデザインパターンのうち,オブジェクト生成に関するものはこの問題を解決するために用意されているといってよい.Curlでは,抽象クラスでもfactory宣言が可能なので,利用者側のコードに具象クラスを全く書かないコーディングも実現できる.詳しく調べたわけではないが,ファクトリーを使えばいくつかのパターンは必要なくなるだろうし,SingletonパターンやFlyweightパターンをもっとスマートに実装できるだろう.
Curlの仕様書でファクトリーを見たとき,かなり感心したと同時になぜ今まで思いつかなかったのだろうとくやしい思いをした.Uniform Accessを他のものに適用すれば,面白いことが見つかるかもしれない.
08:06 PM in Curl | 固定リンク
トラックバック
この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/195810
この記事へのトラックバック一覧です: オブジェクト生成のUniform Access: