VB でインターフェイスの明示的実装
この記事は、Visual Basic Advent Calendar 2016 の 17 日目のエントリーです。16 日目は mmYYmmdd さんの VBAHaskell での関数定義 でした。
今回紹介するネタは特に目新しいものではないのですが、VB でインターフェイスの明示的実装方法を調べるときのググラビリティ向上のために選んでみました。もっとも英語でググる と I'm Feeling Lucky 一発で解答にたどり着けたりしますけど。
現状ググラビリティがもうひとつなのは、Microsoft がなぜか VB においてはインターフェイスの明示的実装という用語を使っていないからです。理由はよくわかりませんが...。
インターフェイスの明示的実装とは
そもそも明示的なインターフェイスの実装って何?ということを念のため確認しておくと、あるインターフェイスのメンバに対して、実装しているクラスの参照変数ではなく、インターフェイスの参照変数を通じてしか呼び出すことができないようにすることです。言葉だけだとちょっとわかりにくいですが、後でサンプルを出します。
どういうときに使うかというと、フレームワークやライブラリで呼び出すために必要なんだけど、ユーザーコードからは使ってほしくないメンバーを実装するときが多いでしょうか。例えば ICloneable とかですかね。詳しい指針は、古い文書ですが MSDN の解説 をご覧ください。
VB での書き方
VB でインターフェイスの明示的実装を行うためには、実装するメンバを Private で修飾します。
Module Module1 Sub Main() Dim one = New Getter() Dim ione = DirectCast(one, IGetOne) ' コンパイルエラー Console.WriteLine(one.GetOne()) ' OK Console.WriteLine(ione.GetOne()) End Sub End Module Interface IGetOne Function GetOne() As Integer End Interface Class Getter Implements IGetOne ' Private にすると明示的実装 Private Function GetOne() As Integer Implements IGetOne.GetOne Return 1 End Function End Class
VB ならではの機能?
上記では明示的実装のために Private を使いましたが、Protected や Friend を指定することもできます。つまり、次のようなこともできます。
Module Module1 Sub Main() Dim one = New Getter() Dim ione = DirectCast(one, IGetOne) ' コンパイルエラー Console.WriteLine(one.GetOne()) ' OK Console.WriteLine(ione.GetOne()) End Sub End Module Interface IGetOne Function GetOne() As Integer End Interface Class Getter Implements IGetOne ' Protected で明示的実装することもできる Protected Function GetOne() As Integer Implements IGetOne.GetOne Return 1 End Function End Class Class Getter2 Inherits Getter Sub action() ' OK Dim one = MyBase.GetOne() End Sub End Class
この例は Protected ですが、正直あまり使いどころがわかりません。ただ、Friend だとそれなりに便利かも、というかフレームワークやライブラリで呼び出すときだけインターフェイスにキャストしなくても良いようにする、という目的だとむしろ Private を使うよりも適切かもしれません。
ちなみにちょっと試した限りでは、C# では明示的実装を行うとそのメンバは常に private 相当になり、protected や internal 相当で明示的実装をすることはできないっぽいので、VB ならではの機能、ということになります。