接口的实现与使用:
一旦定义了接口,一个或更多的类就可以以不同的方式来实现该接口中的功能,并且每个类必须实现该接口中所定义的所有方法、属性、索引或事件。即一个接口可以由多个类实现,而在一个类也可以实现多个接口。
实现接口的方式与继承相同,即将接口放在类名的后面,中间用冒号隔开。
class 类名:接口列表
{
//类实体。。。
}
小资料:
◎ 一个类实现一个接口时,这个类就必须实现整个接口。也就是说,这个类不能选择实现接口的某一部分。
◎ 一个类可以实现多个接口。要实现多个接口时,在上述语句的接口列表之间用逗号隔开。
◎ 一个类可以继承一个基类,并同时实现一个或多个接口的,这时,需要将各个接口用逗号分开,并且基类名必须放在被逗号分隔的接口列表的首位。
◎ 在类中实现的接口成员(方法、属性、索引、事件)必须定义为public 。因为接口中声明的成员默认是public类型的。所以在类中实现接口成员必须是public类型的。另外,在类中实现的成员的数据类型也必须和它们在接口中声明的类型完全一样。
一个类实现(使用)一个接口:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
public interface IDataSeries
{
int getNext();//返回数字系列中的下一个数字
void reset();//重新开始
void setStart(int x);//设置初始值
}
class MyClass1 : IDataSeries
{
int value;
public MyClass1()
{
value = 0;
}
#region IDataSeries 成员
public int getNext()
{
value += 3;
return value;
}
public void reset()
{
value = 0;
}
public void setStart(int x)
{
value = x;
}
#endregion
}
}
从上面的接口成员声明中不需要声明任何访问修饰符,而在类中相应接口成员实现定义中则都用public修饰符。
多个类实现(使用)一个接口:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
public interface IDataSeries
{
int getNext();//返回数字系列中的下一个数字
void reset();//重新开始
void setStart(int x);//设置初始值
}
class MyClass1 : IDataSeries
{
int value;
public MyClass1()
{
value = 0;
}
#region IDataSeries 成员
public int getNext()
{
value += 3;
return value;
}
public void reset()
{
value = 0;
}
public void setStart(int x)
{
value = x;
}
#endregion
}
class MyClass2 : IDataSeries
{
int value;
public MyClass2()
{
value = 0;
}
#region IDataSeries 成员
public int getNext()
{
value += 4;
return value;
}
public void reset()
{
value = 0;
}
public void setStart(int x)
{
value = x;
}
#endregion
}
}
由此可以看出MyClass1和MyClass2这类的对象都实现了IDataSeries接口,也就是说,任何一个类的对象都可以分别实例接口中定义的功能信息,即接口实现了C#的“一个接口,多个方法”的多态性。
一个类实现(使用)多个接口:
一个类实现多个接口也就实现了多重继承。
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
public interface IShape
{
double Area();
double GramLenght();
int Sides { get;}
}
public interface IShapePlay
{
void Play();
}
public class Square:IShape,IShapePlay
{
private int sides;
public int sidesLength;
public Square()
{
sides = 4;
}
#region IShape 成员
public double Area()
{
return ((double)sidesLength * sidesLength);
}
public double GramLenght()
{
return ((double)Sides * Sides);
}
public int Sides
{
get {
return sides;
}
}
#endregion
#region IShapePlay 成员
public void Play()
{
Console.WriteLine("\n计算正方形面积的结果如下:");
Console.WriteLine("边长:{0}",this.sidesLength);
Console.WriteLine("边数:{0}",this.Sides);
Console.WriteLine("面积:{0}",this.Area());
}
#endregion
}
}
从上面的Square类代码可见,由于该类包含两个接口,所以它必须实现两个接口的所有成员。
接口的映射:
接口映射是指在实现接口的类或结构中定位接口成员的实现的过程。
在映射过程中,判断类的某个成员Mc与接口的相应成员Mi匹配的原则是:
◎ 如果Mc和Mi是方法,且它们的名称、返回类型和形式参数都一致,则Mc和Mi匹配。
◎ 如果Mc和Mi是属性,它们的名称和返回类型都一致,且访问器也相同(如果Mc不是显式实现,则允许Mc具有额外的访问器),则Mc和Mi匹配。
◎ 如果Mc和Mi是索引器,它们的名称和形式参数都一致,且具有相同的访问器(如果Mc不是显式实现,则允许Mc具有额外的访问器),则Mc和Mi匹配。
现假设在类或结构C上执行映射过程,查找接口I的成员M的过程,查找过程如下:
◎ 在类C中查找I.M的实现过程。如果C中包含一个与I和M相匹配的显式接口成员实现,则这个成员就被认为是I.M的实现。
◎ 如果在C中没有找到显式接口成员实现,则查找C的所有非静态公共成员,如果某个成员与M相配,则被认为是I.M的实现。
◎ 如果在C中没有找到以上的两种匹配成员,则转到C的基本类中继续查找,直到找到匹配的实现。如果一个没有找到,将会提示错误。
例如:
Class MyClass:interface 1 Class1 interface2 Class2
{
void MyMethod1(){}
void MyMethod2(){}
}
以上代码中,MyClass类使用的是MyMethod1()方法是接口Interface1中声明的。当执行上述代码时,先在MyClass类中查找Interface1接口成员的实现,由于在类MyClass中找到MyMethod1()方法的实现,所以终止了查找运算。然而,如果在MyClass类没有找到MyMethod1()方法的实现,则还将查找基类Class1和Class2。