カスタムDictionaryクラスを作ろう(5)
前回の続きです。
過去記事
Itemプロパティの実装
さあ、ついにItemプロパティの出番です。
それだけです。
仕様を調べる
例によってオブジェクト ブラウザーで仕様を調べます。

Property Item(Key)
となっているので、引数がKeyのプロパティということですね。
さらに、
指定したキーに対する項目を設定します。値の取得も可能です。
とあるので、Read/Writeということです。
また、
Scripting.Dictionaryの既定メンバー
とも書いてあります。これは、このItemプロパティがDictionaryクラスのデフォルトプロパティであることを意味します。
たとえば、Dictionaryのインスタンスdicに、キーが"pachinko"、アイテムが123という要素があったとしたら、本来
dic.Item("pachinko")
とすべきところ、
dic("pachinko")
でもアイテムの123を取り出せる、ということです。
ここまで情報量が多かったので、ちょいと整理しましょう。
Keyという引数(Variant)が要る- 返り値は
Variant型 - Read/Writeともに必要
- デフォルトプロパティである
これだけの条件を踏まえて実装しないといけないわけです。
では、順に潰していきましょう。
実装
Property Getを作る
まずは、Property Getから。
リスト1
Public Function Item(ByVal Key As Variant) As Variant
Item = m_Dictionary.Item(Key:=Key)
End Function
単純に考えると、こうなります。
ただし、これだとうまくいきません。
リスト1-1
Private Sub DictionaryTest01()
Dim dic As Dictionary
Set dic = New Dictionary
Call dic.Add(Key:="pachinko", Item:=123)
Debug.Print dic.Item(Key:="pachinko")
End Sub
これだと

うまくいくのですが、
リスト1-2
Private Sub DictionaryTest02()
Dim dic As Dictionary
Set dic = New Dictionary
Dim sh As Worksheet
Set sh = Application.ActiveSheet
Call dic.Add(Key:="pachinko", Item:=sh)
Debug.Print dic.Item(Key:="pachinko").Name
End Sub
このように、たとえばWorksheet(=Object型のアイテム)を闘魂注入し、そいつを取得しようとすると、

エラーになるのです。
ステップ実行してみると、

このように、クラス モジュールDictionary内の
Item = m_Dictionary.Item(Key:=Key)
この行でエラーになっています。
エラーメッセージは
オブジェクトは、このプロパティまたはメソッドをサポートしていません。
なので、素直に読むと(m_Dictionaryの実体である)Scripting.DictionaryがItemプロパティをサポートしていないように誤認してしまいますが、そんなはずはありません。
察しの良い方はもうお気づきだと思いますが、察しの悪い方のために申しましょう。
Item = m_Dictionary.Item(Key:=Key)
この代入のしかたに問題があるのです。
そう。Object型のアイテムを変数等に代入するときは〝Setが必須〟なのでした。
それが証拠に、リスト1の
Item = m_Dictionary.Item(Key:=Key)
を
Set Item = m_Dictionary.Item(Key:=Key)
にしてやると、

このようにちゃんと意図した結果が得られます。
そこで、実装を変更します。
リスト1改
Public Property Get Item(ByVal Key As Variant) As Variant
If IsObject(m_Dictionary.Item(Key:=Key)) Then
Set Item = m_Dictionary.Item(Key:=Key)
Else
Item = m_Dictionary.Item(Key:=Key)
End If
End Property
IsObject()関数を用いて、アイテムの型を判定し、Object型だったらSetを付けるようにしています。
リスト1-3
Private Sub DictionaryTest03()
Dim dic As Dictionary
Set dic = New Dictionary
Call dic.Add(Key:="pachinko", Item:=123)
Dim sh As Worksheet
Set sh = Application.ActiveSheet
Call dic.Add(Key:="slot", Item:=sh)
Debug.Print dic.Item(Key:="pachinko")
Debug.Print dic.Item(Key:="slot").Name
End Sub
これで動作確認すると、

このとおり、ちゃんと値型にもObject型にも対応できています。
おわりに
この時点で、結構長くなってしまったので、続きは次回!
このItemプロパティをデフォルトプロパティにしていきましょう。