VB.NETでInterfaceを実装する方法

こんにちは!
今日は「VB.NETでInterfaceを実装する方法」について、がっつり書きたいと思います。


1. そもそも Interface って何者?

いきなり専門用語から始まると眠くなりがちなので、まずは生活の例でイメージしてみましょう。
インターフェースは“取り決めだけ書かれた契約書”みたいなものです。

  • 契約書にサイン(=Implements)したクラスは、そこに書かれた項目を 必ず実装 しなければなりません。
  • 逆に言えば、契約書には「こういう手続きはこう書きなさい」という 中身(処理) はありません。

具体的にはこんなコードで定義します。

' 動物が持つべき振る舞いの契約書
Public Interface IAnimal
    Property Name As String
    Sub Speak()
End Interface

ここには Name プロパティと Speak() メソッドが「あるべし」とだけ書かれています。
“どうやって鳴くか” は、後でクラスが自分で決めるわけですね。


2. ありがちな誤解と落とし穴

「継承(Inherits)と何が違うの?」

これ、実はよく聞かれる質問です。
継承は親クラスの実装も丸ごともらうのに対し、インターフェースはシグネチャ(名前と引数)だけもらうのがポイントです。

もうひとつの落とし穴は Implements を書き忘れてビルドエラーになるパターン。
Visual Studio が “○○を実装してないよ” と赤線を引いてくれるものの、最初はドキッとします。
初心者の頃は私も何度も心臓が縮みました……。


3. 基本の実装ステップ 5 連発

ステップやることワンポイント
1Interface を宣言するまずは契約書を書く
2クラスの後ろに Implements を書く複数可 (Implements IAnimal, IDrivable など)
3メンバーを実装するImplements IAnimal.Speak のように明示
4Option Explicit/Strict を ON にする未実装を早期発見
5テストで契約を確かめるダックタイピング的に動作確認

それでは、王道パターンを見てみましょう。

' 1. 契約書
Public Interface IAnimal
    Property Name As String
    Sub Speak()
End Interface

' 2. 契約書にサイン
Public Class Dog
    Implements IAnimal

    ' 3. 契約条項を具体化
    Private _name As String

    Public Property Name As String Implements IAnimal.Name
        Get
            Return _name
        End Get
        Set(value As String)
            _name = value
        End Set
    End Property

    Public Sub Speak() Implements IAnimal.Speak
        Console.WriteLine($"{Name}:ワン!")
    End Sub
End Class
  • Implements IAnimal をクラスヘッダーに。
  • 各メンバーにも Implements IAnimal.Xxx を付けるのが VB.NET 流のお作法です。

C# の “コロンで列挙し、メンバーには何も書かない” スタイルとちょっと違うので注意してください。


4. 複数インターフェースを同時に使う

現実世界で「話せて、走れて、泳げる」生き物がいるように、クラスは複数の契約書を同時に満たすことができます。

Public Interface IRunnable
    Sub Run()
End Interface

Public Interface ISwimmable
    Sub Swim()
End Interface

Public Class Labrador
    Implements IAnimal, IRunnable, ISwimmable

    ' IAnimal
    Public Property Name As String Implements IAnimal.Name

    Public Sub Speak() Implements IAnimal.Speak
        Console.WriteLine($"{Name}:ワンワン!")
    End Sub

    ' IRunnable
    Public Sub Run() Implements IRunnable.Run
        Console.WriteLine($"{Name} は全力疾走!")
    End Sub

    ' ISwimmable
    Public Sub Swim() Implements ISwimmable.Swim
        Console.WriteLine($"{Name} は犬かき中…")
    End Sub
End Class

「多重継承は危険」と言われても、多重インターフェースは安全です。
実装が衝突せず、シンプルに責務を分けられるのが嬉しいところですね。


5. Interface 継承というテクニック

インターフェース同士でも “子孫” を作れます
例えば「動物でありつつ、空も飛べる」という要件なら:

Public Interface IFlyableAnimal
    Inherits IAnimal   ' ← ここポイント
    Sub Fly()
End Interface

使う側は IFlyableAnimal ひとつを実装するだけで、IAnimal の契約も自動的に背負うわけです。
こうすると 「ある機能を必ずセットで実装させたい」 というケースに便利です。


6. よくある Q&A

Q1. インターフェースに処理を書けないの?

今の VB.NET では “デフォルト実装” はサポートされていません(C# 8 では可能ですが)。
「契約は契約だけ」に徹する――これが Visual Basic 的な哲学です。

Q2. Implements を書くのが面倒なんだけど?

Visual Studio でクラス名の上にカーソルを置いて [Ctrl] + [.](クイックアクション)→「インターフェイスのメンバーを実装」を選ぶと自動生成してくれるので時短になります。

Q3. Implements を付け忘れたら?

Option Strict/Explicit を ON にしておくと、未実装のメンバーをコンパイルエラーで即発見できます。
プロジェクトプロパティからチェックボックスをポチっとするだけなのでオススメです。


7. 「抽象クラスでいいのでは?」問題に一石

一般論としては「実装を共有したければ抽象クラス、共有しなければインターフェース」と言われます。
ただ、私の経験上――

  • 将来の多重継承フラグ を感じたら、まずインターフェースで切り出す
  • “共通実装を 必ず 持たせたい” と確信できるまで抽象クラスは温存

という戦略の方が、保守コストが下がりました。
抽象クラスを先に作りすぎると、後で「もう一個継承したいけどできない…」となりがちなんです。


8. テスト面から見た Interface の強み

インターフェースが映えるのは ユニットテスト です。
モックやスタブをサッと差し替えられるので、依存性注入(DI)がぐっと楽になります。

' テストダブル
Public Class FakeAnimal
    Implements IAnima
    Public Property Name As String Implements IAnimal.Name
    Public Sub Speak() Implements IAnimal.Speak
        Console.WriteLine("(テスト用に無言)")
    End Sub
End Class

本番コードの DogFakeAnimal に入れ替えてテストすれば、
「外部 API に吠えまくってログが汚染される」なんて事故も防げます。


9. まとめ 〜インターフェースは“契約書”〜

  • Interface = 実装を持たない契約書。複数同時に背負っても OK。
  • Implements を忘れると赤線祭り。自動生成&Option Strict で防御しましょう。
  • 抽象クラスとの使い分けは「多重継承の可能性」と「共有実装の必然性」で判断すると吉。
  • ユニットテストや DI と相性抜群。未来の自分が感謝します。

というわけで、インターフェースを味方につけると 保守性・拡張性・テスト容易性 の三拍子が揃います。
もし「継承かインターフェースか」で迷ったら、「このロジックは契約だけで十分?」と自問してみてください。

今日はここまで!
この記事が「インターフェースって実は良いヤツだな」と感じるきっかけになれば嬉しいです。