接口是 指定一组函数成员而不实现它们的引用类型。
在使用C#时不同于之前学习的 JavaScript,python 这些高级动态语言,它对于很多东西都要严格处理。就比如说想要创建一个类似共用的方法,用以输出传入参数对象的 classname
属性,然而当你把该方法的传入参数对象类型定为 类型A
,此时该方法的签名就已经确定了,再想传入 类型B
输出 classname
属性就会报错。
而接口就能解决这种问题,个人认为接口在这里就起到一个 包装、封装 的作用。使用接口就像在外再包装一个基类,里头声明未定义的函数成员,而应用个体派生自这个类,未定义的函数成员也必须在此定义。
这样就能解决一些公共方法调用不同类型的数据会报错的尴尬。
关于使用接口,主要可分为以下几个步骤:
- 声明接口
- 实现接口,实现接口成员
1 声明接口
关于接口声明,要知道以下重点事项:
- 使用
interface
关键字 - 接口成员不能包含 数据成员 和 静态成员,接口成员只能包含以下非静态成员函数的声明:
- 方法
- 属性
- 事件
- 索引器
- 声明的接口成员 不能包含任何实现代码,而在声明的主题后面使用分号
;
代替实现代码 - 按惯例,接口的名称必须以大写
I
开头 - 接口声明可以有任何的访问修饰符:
public
,protected
,internal
或private
- 而接口成员只能有一个
public
修饰符,这是默认的,显式添加public
也会报错 - 接口也可以继承
例如:
public interface IMyInterface2
{
int Method1(int nVar1); // 接口成员不容许访问修饰符,不用实现方法主体,而使用分号
}
2 实现接口
只有类和结构能够实现接口,要实现接口,类或结构必须:
- 在 基类列表 中包括 接口名称(一个类或结构可以实现多个接口,而只能继承一个基类)
- 为每一个 接口的成员 提供实现
例如:
// MyBaseClass 是基类,往后的两个是接口名称
class Derived:MyBaseClass,IIfc1,Icomparable
{
... // 实现接口成员代码
}
完整例子:
// 声明接口
interface IInfo
{
string GetName(); // 接口成员必须是函数成员
}
// Men类实现接口,并在其中实现接口成员
class Men:IInfo
{
public string Name;
public string GetName() { return Name; }
}
// women类实现接口,并在其中实现接口成员
class Women:IInfo
{
public string FirstName;
public string LastName;
public string GetName()
{
string FullName = FirstName + LastName;
return FullName;
}
}
class Progarm
{
// 应用接口的公共方法
static void PrintInfo(IInfo item)
{
Console.WriteLine("Name: {0}", item.GetName());
}
// 主程序
static void Main()
{
Men people1 = new Men(){Name = "Seiei Leung"};
Women people2 = new Women(){FirstName = "Seiei", LastName="Leung"};
PrintInfo(people1); // 对象引用能自动转换为它们实现的接口引用
PrintInfo(people2); // 对象引用能自动转换为它们实现的接口引用
}
}
3 接口的引用
接口是引用类型,由上面的例子可以看出,我们可以把类对象引用隐式转换为接口类型,从而获取其 相应指向 接口的引用(强制转换也可以)。
IIfc1 ifc = (IIfc1) mc; // 获取接口的引用
ifc.PrintOut("interface"); // 使用接口的引用调用方法
3.1 as
运算符
当类没有实现接口成员时,强制转换成接口引用会报错,此时使用 as
运算符,当类没有实现接口成员时,会返回 null
,而不是报错
IIfc1 ifc = mc as IIfc1; // 获取接口的引用
if (ifc != null)
{
ifc.PrintOut("interface");
}
4 接口成员的实现
接口成员的实现有以下几种:
- 类级别实现
- 基类级别实现
- 显式接口成员实现
4.1 基类成员作为实现
实现接口的类可以从它的基类继承实现的代码
4.2 显式接口成员实现
希望为每个接口分离实现接口成员,需要创建 显式接口实现。
显式接口成员使用 限定接口名称 声明,由接口名称、成员名称以及连接二者的点分隔号组成,eg:
void IIfc1.PrintOut(string s)
{
...
}
此时的接口成员并不是平常一样引用,指向对象类中实现成员,而是直接代表实际代码。
4.2.1 访问显式接口成员实现
显式接口成员实现只可以通过指向接口的引用访问,也就是说类的其他成员也不能直接访问它们,eg:
class Myclass: IIfc1
{
void IIfc1.PrintOut(string str)
{
Console.WriteLine(str);
}
public void Method1()
{
((IIfc1)this).PrintOut('Seiei'); //类的内部也要转换接口的引用
}
}