
C#のinterface(インターフェイス)とは?分かりやすく解説!
目次
C#のinterfaceをわかりやすく解説!
C#のinterfaceとは?
C#のinterface(インターフェイス)はオブジェクト指向プログラミングをする上で必須の機能です。この記事ではinterfaceを全く知らない人、interfaceをなんとなく使っている人にわかるように説明するので、是非ご覧ください。
interfaceの目的や意義について長々と説明するより、まずはC#のサンプルプログラムで実践的に理解して行きましょう。以下をご覧ください。
interface IWalk
{
void Walk();
}
class Human : IWalk
{
public void Walk()
{
Console.WriteLine(“”ウォーキングをします。””);
}
}
インターフェイスはクラスにメソッドの記述を強制できる
上のサンプルの説明をすると、IWalkというインターフェイスをHumanというクラスに実装をしています。「class Human : IWalk」と記述していますが、これでIWalkを「実装」しています。なお:の右にインターフェイスでなくクラスを記述した場合は、「継承」と言います。
IWalkにはWalkメソッドの中身がありませんが、これがインターフェイスの特長です。IWalkを実装したHumanには同名のWalkメソッドがありますが、もしこれを記述しないと、HumanにWalkメソッドが無いというエラーになります。
つまり、インターフェイスは実装したクラスに特定の名前のメソッドの記述を強制する機能があるということです。
インターフェイスを使うとどんな利点があるの?
これだけではインターフェイスが何の役に立つのかわからないと思います。サンプルに以下を追加しましょう。なおソースの先頭には「using System.Collections.Generic;」を記述してください。
class Dog : IWalk
{
public void Walk()
{
Console.WriteLine(“”散歩をさせられています。””);
}
}
static void Main(string[] args)
{
// IWalk型のListにHumanクラスとDogクラスを追加
List<IWalk> list = new List<IWalk>();
list.Add(new Human());
list.Add(new Dog());
// List内のクラスのWalkメソッドを実行
for (int i = 0; i < list.Count; i++)
{
list[i].Walk();
}
}
インターフェイスでポリモーフィズムを実現できる
実行すると
ウォーキングをします。
散歩をさせられています。
と表示されます。Human型とDog型は別のクラスですが、どちらもIWalkというインターフェイスを実装することで、Walkメソッドがあることが保証されます。そのためこのようにIWalk型で一括で取り扱うことができるのです。
この手法はオブジェクト指向の概念の1つである「ポリモーフィズム(多態、多様)」と言われます。多様性のあるクラスを1つの「インターフェイス」でひとくくりに扱うことが出来るのです。インターフェイスのおかげで簡潔でわかりやすいプログラムを作ることができますね。
インターフェイスと抽象クラス
なおC#にはインターフェイスと似た機能を持つ抽象クラスがあります。ここまでのサンプルを以下のように直しても、全く同じように動作します。
abstract public class IWalk
{
abstract public void Walk();
}
class Human : IWalk
{
public override void Walk()
{
Console.WriteLine(“”ウォーキングをします。””);
}
}
class Dog : IWalk
{
public override void Walk()
{
Console.WriteLine(“”散歩をさせられています。””);
}
}
インターフェイスと抽象クラスはどう違うの?
抽象クラスでもインターフェイスとほぼ同じことが出来ますが、2つは別物です。抽象クラスは継承した子クラスにoverrideを強制して共通のメソッドを持たせるためのクラスで、インターフェイスは実装したクラスに共通のメソッドを持たせるという違いがあります。
インターフェイスは「class Human : IWalk, ITalk」のように1つのクラスに複数実装できますが、C#はC++のような多重継承を禁じているため、クラスが親として持てる抽象クラスは1つだけです。JavaやC#のインターフェイスは、C++の多重継承で行われていたことを、スマートな形で実現するための機能なのです。
インターフェイスと抽象クラスの現状
抽象クラスはインスタンスを生成できない(newできない)という制約はあるものの、普通のクラスのようにクラスフィールドやメソッドを記述できます。しかしインターフェイスはメソッドの記述を強制する目的のみの機能のため、クラスフィールドは記述できません。またメソッドの中身も書けず、また全てのメソッドをpublic扱いにする必要がありました。
ただしC# Ver. 8.0からはインターフェイスで出来ることが増えて、メソッドの中身を「デフォルト処理」として書くことが出来るようになりました。これによってデフォルト処理があれば、実装したクラスにインターフェイスのメソッドが無くてもエラーにならなくなりました。
さらにpublic以外のアクセス修飾子も使えるようになり、静的(static)なクラスフィールドを持てるようになっています。その結果、C# Ver. 8.0のインターフェイスは「動的なクラスフィールドは持てないが多重継承ができる抽象クラス」のようになっています。
C# Ver. 8.0のインターフェイスのサンプル
C# Ver. 8.0でインターフェイスどう変わったかのサンプルです。ここまでのサンプルのIWalkとMainメソッドを以下のように修正し、Flowerクラスを追加してみてください。
interface IWalk
{
private static String message = “”歩けません。””;
void Walk()
{
// デフォルト処理
Console.WriteLine(message);
}
}
class Flower : IWalk
{
// 花は歩けません
}
static void Main(string[] args)
{
List<IWalk> list = new List<IWalk>();
list.Add(new Human());
list.Add(new Dog());
list.Add(new Flower());
for (int i = 0; i < list.Count; i++)
{
list[i].Walk();
}
}
結果は、
ウォーキングをします。
散歩をさせられています。
歩けません。
となります。C# Ver. 8.0以降のインターフェイスには注意しましょう。
複数のインターフェイスに同じメソッドがあった場合は?
ここまで読んで鋭い人は「もし複数実装したインターフェイスに同じ名前のメソッドがあったらどうするの?」と思うでしょう。C#にはそれを回避する方法はあります。以下をご覧ください。
interface IWalk1
{
void Walk();
}
interface IWalk2
{
void Walk();
}
class Human : IWalk1, IWalk2
{
void IWalk1.Walk()
{
Console.WriteLine(“”Walk1のWalkです。””);
}
void IWalk2.Walk()
{
Console.WriteLine(“”Walk2のWalkです。””);
}
}
static void Main(string[] args)
{
IWalk1 w1 = new Human();
IWalk2 w2 = new Human();
w1.Walk();
w2.Walk();
}
明示的な記述でメソッド名の衝突を回避できる
上のサンプルを実行すると、
Walk1のWalkです。
Walk2のWalkです。
と表示されます。インターフェイスを実装したクラスのメソッドを「インターフェイス名+.+メソッド名」とすることで、どのインターフェイスのメソッドを記述したのかを明示できるのです。それにより呼び出すメソッドを切り替えることができています。
なおサンプルにあるように明示的な記述をする時はpublicは外します。これは特定のインターフェイスのみに使用を限定するからです。なお上のHumanクラスを以下のようにした場合、IWalk1とIWalk2の両方に対応します。
class Human : IWalk1, IWalk2
{
public void Walk()
{
Console.WriteLine(“”Walk1でもWalk2でも呼び出せます。””);
}
}
さいごに
C#のインターフェイス(interface)を説明しましたがいかがでしたでしょうか。interfaceはオブジェクト指向には欠かせない機能ですが、C# Ver. 8.0から機能が増えて注意が必要になりました。インターフェイス本来の使用目的から外れないように気を付けましょう。