VBAでのInterfaceやキャスト
前段
個人的に、Excel VBAを仕事で組む機会がある。 自由に組んでいるので、いろいろと設計方法、実装方法を考える。VBAのインターフェース
VBAにはJavaでいうextendsのような継承はない。 Interfaceがあるので、ポリモーフィズムを実現するときは、これを使うのが一つの方法論だ。 ただ、インターフェースは、というか、VBAはクラスのキャストができない。 インターフェイス自体が、そうする性質のものではないのだが、つい欲しくなるときがある。Object型
さて、話は変わるが、VBAには、Object型というものがある。 平たく言うと、あらゆるクラスに適する型である。あらゆるクラスのスーパークラスと思うと話が早い。そして、Objcet型からは元のクラスで実装したプロシージャを呼ぶことができる。ObjectによるポリモーフィズムもVBAでは可能、といえる。
なので、ダウンキャストを実現するために、インターフェイスでインスタンスが自己をObjectで出力するためのメソッドを定義してあげることで、スーパークラスからサブクラスへのキャストを実現する。
実装例
Class InterfaceClass
'' プロパティ
Public porp as String
'' イミディエイトウィンドウに出力する
Public Sub printOut() As String
End Sub
'' 自己をObject型で出力する
Public Function Object() As Object
End Function
Class ImplementClass
'' InterfaceClassを実装する
Implements InterfaceClass
'' スーパークラスのGet,Letのため、
'' 値を保持しておくためのプロパティ
Private prop As String
'' Getter
Public Property Get InterfaceClass_prop() As String
InterfaceClass_prop = prop
End Property
'' Letter
Public Property Let InterfaceClass_prop(RMS As String)
prop = RMS
End Property
'' printOutプロシージャの実装
'' Debug.Print で出力する
Public Sub InterfaceClass_printOut() As String
Debug.print "Hello, " & prop
End Sub
'' Objectプロシージャの実装
'' 単純に、自身をObject型として出力する
Public Function Object() As Object
Set Object = Me
End Function
'' サブクラスとしてのプロシージャ
'' メッセージボックスを表示させる。
'' このメソッドは、サブクラスとして実行することはできる。
'' ただ、スーパークラスからは呼び出すことはできない。
Public Sub outputMessage() As String
MsgBox "Welcome, " & prop
End Sub
MainModule
Public Sub Main()
Dim ins As InterfaceClass
'' ImplementClassのインスタンスをinsに格納する
Set ins = New ImplementClass
ins.prop = "Neko"
'' InterfaceClassとしてprintOutを実行
Call ins.printOut '' Hello, Neko としてイミディエイトウィンドウに出力
'' outputMessageはスーパークラスとしては呼ぶことができない
'' ins.outputMessage '' Errorになる
'' ImplementClassとしての変数
Dim obj As ImplementClass
'' そのままInterfaceクラスのそれをSetすることはできない
'' Set obj = ins '' Errorになる
'' ObjectプロシージャでObject型として出力することで、
'' ダウンキャストが可能
Set obj = ins.Object
obj.outputmessage '' MessageBoxで「Welcome, Neko」として出力する
obj.printOut '' イミディエイトウィンドウに「Hello, Neko」として出力することもできる
End Sub
コメント
コメントを投稿