インターフェース
C#のインターフェイスは、構文的には抽象クラスに似ています。抽象メンバーのコレクションを形成するために、いくつかの抽象メソッド、属性、インデクサー、およびイベントを定義します。各メンバーは通常、特定のものを反映します。アスペクト関数。インターフェイスは基本的に、特定の機能または機能に関する合意です。
プログラムのインターフェースの有用性は、主に次の側面に反映されています。
- 無関係なクラスの同じ動作は、これらのクラス間の階層関係を考慮する必要なしに、インターフェースを介して実現できます。
- インターフェイスを介して、複数のクラスが実装する必要のあるメソッドを指定できます。
- インターフェイスを介して、オブジェクトに対応するクラスを知らなくても、オブジェクトのインタラクティブインターフェイスを理解できます。
インターフェイスを定義する
interface
キーワードを使用してインターフェースを定義します。インターフェースには複数のメンバーが存在する場合があります。
インターフェイスのメンバーは、抽象メソッド、プロパティ、イベント、またはインデクサーである必要があり、これらの抽象メンバーには実装本体がありません。インターフェイスには、定数、フィールド、演算子、コンストラクター、静的コンストラクター、またはネストされた型を含めることはできません。また、任意の型の静的メンバーを含めることもできません。
すべてのインターフェイスメンバーは、暗黙的にパブリックアクセス可能public
です。つまり、暗黙的にyesです。ただし、new
これら以外の修飾子は、インターフェイスメンバーの宣言では使用できません。しかし、インタフェース自体は、次のような修飾子を取ることができpublic
、interface
。コーディング規約によれば、インターフェイスの名前はすべて大文字のIで始まります。例:
public interface IStringList
{
void Add(string s);
int Count{
get;}
string this[int index]{
get; set;}
}
このインターフェイスには、メソッド、プロパティ、およびインデクサーが含まれています。
インターフェイスは、1つ以上のベースインターフェイス(親インターフェイス)から継承できます。例:
interface IMyInterface:IBase1, IBase2
{
void MethodA();
void MethodB();
}
サブインターフェイスは、親インターフェイスのすべてのプロパティとメソッドを継承します。new
修飾子を使用して、親インターフェイスのメンバーを非表示にすることもできます。
たとえば、次の定義System.Collections.IList
:
public interface IList:ICollection, IEnumerable
{
bool IsFixedSize{
get;}
bool IsReadOnly{
get;}
object this[int index]{
get; set;}
int Add(object value);
void Clear();
bool Contains(object value);
int IndexOf(object value);
void Insert(int index, object value);
void Remove(object value);
void RemoveAt(int index);
}
インターフェイスを実装する
インターフェイスの宣言は、プログラム開発の初期段階でのプロトコルのセットに相当する抽象メソッドのみを提供します。インターフェイスで指定された機能を具体的に実現するには、特定のクラスがインターフェイスで抽象メソッドのステートメントを記述する必要があります。実際のメソッド本体を定義します。
インターフェイスは、クラスまたは構造体によって実装できます。以下は、クラスを使用してインターフェースを実装する形式です。
class 类名:[父类,] 接口, 接口, ..., 接口
{
...
}
クラスがインターフェースを実装するときは、次の問題に注意してください。
- クラスの宣言部分で、コロン(
:
)を使用して、その親クラスと実装するインターフェイスを示します。親クラスは、インターフェイス名の前に配置する必要があります。親クラスが省略されている場合、暗黙の親クラスはSystem.Object
です。 - クラスがインターフェイスを実装する場合、クラス内のインターフェイスの各メンバーに対応するメンバーを検索できる必要があります。また、インターフェイスのすべての親インターフェイスのすべてのメンバーを検索できる必要があります。もちろん、このようなメンバーは、このクラスで定義することも、このクラスの親クラスから継承することもできます。
- 抽象クラスがインターフェイスを実装する場合、すべてのメンバーに実装プログラムを提供する必要もあります。抽象クラスは、インターフェイスメソッドを抽象メソッドにマップできます。
- クラスは親クラスを1つだけ持つことができますが、同時に複数のインターフェースを実装できます。クラスが複数のインターフェースを実装する場合、インターフェースが特別なクラスとして理解されると、このクラスは実際にインターフェースを使用して複数の親クラスを取得します。つまり、多重継承が実現されます。
- インターフェイスの抽象メソッドの暗黙的なアクセス制御に特に注意してください
public
。そのため、クラスはメソッドを実装するときにpublic
修飾子を使用する必要があります。
例:
using System;
namespace ConsoleApp3接口
{
interface Runner
{
void run ();
}
interface Swimmer
{
void swim ();
}
abstract class Animal
{
abstract public void eat ();
}
class Person : Animal, Runner, Swimmer
{
public void run () {
Console.WriteLine ("run");
}
public void swim () {
Console.WriteLine ("swim");
}
public override void eat () {
Console.WriteLine ("eat");
}
public void speak () {
Console.WriteLine ("speak");
}
}
class TestInterface
{
static void m1 (Runner r) {
r.run ();
}
static void m2 (Swimmer s) {
s.swim ();
}
static void m3 (Animal a) {
a.eat ();
}
static void m4 (Person p) {
p.speak ();
}
public static void Main (string[] args) {
Person p = new Person ();
m1 (p);
m2 (p);
m3 (p);
m4 (p);
Runner a = new Person ();
a.run ();
}
}
}
インターフェースへの参照
インターフェイスは参照型として使用でき、クラスによって実装されたインターフェイスのメソッドには、これらの参照変数を介してアクセスできます。例:Person
クラスが実装されISwimmable
ているPerson
場合、オブジェクトをISwimmable
次のように参照できます。
Person p = new Person();
ISwimmable s = p;
同様に、メソッドがパラメーターとしてインターフェースを必要とする場合、インターフェースを実装するクラスのインスタンスオブジェクトを直接渡すことができます。データ型としてのインターフェースは、オブジェクトに対応する特定のクラスを知る必要はありませんが、その対話型インターフェースまたは機能に焦点を合わせています。
インターフェイスに複数の親インターフェイスがあり、インターフェイスのメンバーが同じ名前である可能性があるため、インターフェイスメンバーを呼び出すときに、あいまいさが生じる可能性があります。例えば:
interface IList
{
int Count{
get; set;}
}
interface ICounter
{
void Count(int i);
}
interface IListCounter : IList, ICounter{
}
class C
{
void Test(IListCounter x){
x.Count(1); // Error, Count不明确
x.Count = 1; // Error, Count不明确
((IList)x).Count = 1; // Ok, 调用IList.Count.set
((ICounter)x).Count(1); // Ok, 调用ICounter.Count
}
}
インターフェイスメンバーの実装を表示する
複数のインターフェースが同じ署名メソッド(または他のメンバー)を持っている場合があります。クラスが複数のインターフェースを同時に実装する必要がある場合、各インターフェースの要件を満たすために使用できるメソッドは1つだけです。ただし、多くの場合、各インターフェイスでのこれらの同じ署名メソッドの意味は同じではないため、クラスが各インターフェイスを実装するときは、実装するインターフェイスのメソッドを表示する必要があります。例えば:
using System;
namespace ConsoleApp3接口
{
class InterfaceExplicitImpl
{
static void Main (string[] args) {
FileViewer f = new FileViewer ();
f.Test ();
((IWindow)f).Close ();
IWindow w = new FileViewer ();
w.Close ();
}
}
interface IWindow
{
void Close ();
}
interface IFileHander
{
void Close ();
}
class FileViewer : IWindow, IFileHander
{
void IWindow.Close () {
Console.WriteLine ("Window Closed");
}
void IFileHander.Close () {
Console.WriteLine ("File Closed");
}
public void Test () {
((IWindow)this).Close ();
}
}
}
以上のことから、ディスプレイインターフェイスメンバー実装プログラムは、他のメンバーと比較してアクセス機能の特性が異なることがわかります。ディスプレイインターフェイスメンバーはクラスインスタンスを介して呼び出すことができないため、この意味ではプライベートです。一方、ディスプレイインターフェイスメンバーは、インターフェイスインスタンスを介してアクセスできます。つまり、パブリックです。
ディスプレイインターフェイスメンバーの実現には、主に2つの目的があります。
- これは、クラスまたは構造体インスタンスを介してインターフェイスメンバーにアクセスできず、インターフェイスを介してのみアクセスできることを示しているためです。したがって、インターフェイスのみにアクセスできる状況を説明するためによく使用されます。
- 表示インターフェイスメンバー実装プログラムを使用すると、同じシグニチャでインターフェイスメンバーを明確にすることができるため、クラスまたは構造体には、同じシグニチャで戻り値の型が異なるメンバーを含めることができます。