こんにちは!
今日は「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 連発
ステップ | やること | ワンポイント |
---|---|---|
1 | Interface を宣言する | まずは契約書を書く |
2 | クラスの後ろに Implements を書く | 複数可 (Implements IAnimal, IDrivable など) |
3 | メンバーを実装する | Implements IAnimal.Speak のように明示 |
4 | Option 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
本番コードの Dog
を FakeAnimal
に入れ替えてテストすれば、
「外部 API に吠えまくってログが汚染される」なんて事故も防げます。
9. まとめ 〜インターフェースは“契約書”〜
- Interface = 実装を持たない契約書。複数同時に背負っても OK。
Implements
を忘れると赤線祭り。自動生成&Option Strict で防御しましょう。- 抽象クラスとの使い分けは「多重継承の可能性」と「共有実装の必然性」で判断すると吉。
- ユニットテストや DI と相性抜群。未来の自分が感謝します。
というわけで、インターフェースを味方につけると 保守性・拡張性・テスト容易性 の三拍子が揃います。
もし「継承かインターフェースか」で迷ったら、「このロジックは契約だけで十分?」と自問してみてください。
今日はここまで!
この記事が「インターフェースって実は良いヤツだな」と感じるきっかけになれば嬉しいです。