カスタムDictionaryクラスを作ろう(5)

カスタムDictionaryクラスを作ろう(5)

akashi-keirin.hatenablog.com

前回の続きです。

過去記事

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.DictionaryItemプロパティをサポートしていないように誤認してしまいますが、そんなはずはありません。

察しの良い方はもうお気づきだと思いますが、察しの悪い方のために申しましょう。

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プロパティをデフォルトプロパティにしていきましょう。

akashi-keirin.hatenablog.com