このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
さて、昨日の考察ででてきた、
ヒント値の配列のラッパを作成しよう。
列挙はできないが PuzzleHintCollection という名前にする。
不変クラスということで、値の設定はコンストラクタのみ。
コンストラクタで受け取るのは、ヒント値の配列だ。
IPuzzleLoader との親和性を考えて、
ArrayList で受け取る形にしよう。
後は参照系のプロパティが殆どという形となる。
例によって必要なプロパティを洗い出す。
・ヒントの値:(インデクサ・読み取り専用)
・ヒント数:Count
実はこれだけだ。あとは、内部で後々使えそうなものを、
Friend プロパティとして追加しとこう。
・ヒントの数値合計: Total
・ヒント全体が占有する最小の長さ: MinimumLength
不変オブジェクトは値が変更されないため、
プロパティ値のキャッシュを効かせやすい。
Total や MinimumLength などは、
ヒント値の配列から計算できるが、
最初に一度だけ計算して記憶しておくと速くなる。
Friend は、内部(internal)アクセスを意味し、
同じプロジェクト内でしか参照できない。
Excel VBA では、外から参照とかは考えにくいが、
今後ソースを移植する時のことを考えておく。
では、実装してみよう。
========== クラスモジュール: PuzzleHintCollection ==========
Option Explicit
'##################################################
'# 行または列のヒントを格納した不変クラス
'##################################################
' ヒント値
Private m_oHints() As Long
' 統計情報(キャッシュ)
Private m_lTotal As Long
Private m_lMinimumLength As Long
' コンストラクタ代わり
Friend Sub Construct(ByVal HintValues As ArrayList)
Dim i As Long
ReDim m_oHints(0 To HintValues.Count - 1)
' ヒント値をコピーすると共に、
' 統計情報を先に計算しておく
m_lTotal = 0
For i = 0 To HintValues.Count - 1
m_oHints(i) = CLng(HintValues(i))
m_lTotal = m_lTotal + m_oHints(i)
Next
m_lMinimumLength = m_lTotal + HintValues.Count - 1
End Sub
' ヒントの数値を取得する(既定のプロパティ)
Public Property Get Item(ByVal Index As Long) As Long
Item = m_oHints(Index)
End Property
' ヒント数を取得する
Public Property Get Count() As Long
Count = UBound(m_oHints) + 1
End Property
' ヒントの数の合計を取得する
Friend Property Get Total() As Long
Total = m_lTotal
End Property
' ヒント全体が占有する最小の長さを返す
Friend Property Get MinimumLength() As Long
MinimumLength = m_lMinimumLength
End Property
========== end of PuzzleHintCollection ==========
コンストラクタでの引数チェックはしていない。
Nothing が渡されたり ArrayList が 0 要素だと問題がある。
また、ヒント値が負の値とか、数値でないとか、
調べなければならないことは沢山ある。
(Long の配列を ByRef で受けるって手もあったが)
後は、ArrayList の時のようにトリックを使って、
Item プロパティに既定属性を付けるだけだ。
エクスポートし、テキストエディタで開き、
Property Get Item の下の行に以下を追加する。
Attribute Item.VB_UserMemId = 0
' ヒントの数値を取得する(既定のプロパティ)
Public Property Get Item(ByVal Index As Long) As Long
Attribute Item.VB_UserMemId = 0
Item = m_oHints(Index)
End Property
後は保存してインポートで OK。
プロパティを読み取り専用とし、
Public プロパティの値に関わるフィールドを
変更するメソッドを定義しなければ、
不変クラスのできあがりだ。