接口
接口
接口允许包含方法、属性、索引器和事件的签名,这里只允许包含签名,而不能包含实现(但在C#8.0中可以有方法的[默认实现][2]),接口不能包含常量、字段、运算符、实例构造函数、析构函数以及任何静态成员。
接口特点:
- 接口可以从一个或多个基接口继承(或叫实现),一个类或者结构可以实现多个接口
- 接口只允许包含方法、属性、索引器和事件的签名,这里只允许包含签名,而不能包含实现(在C#7语法中可以有实现)
- 接口不能包含常量、字段、运算符、实例构造函数、析构函数以及任何静态成员
- 接口的成员默认是公共的(public),且不可以再显式声明为public,否则将产生编译异常
- 接口不能被实例化,接口的声明是抽象的(底层实现上)
- 实现接口的类必须实现接口的所有成员,不管是方法、属性、索引器还是事件
定义接口
接口的访问修饰符(默认为internal),可用public,但对于接口的成员,不能使用访问修饰符(默认public),但不能写出来。接口也支持parital进行分部处理。
// 默认internal, 可显式地设定为public和internal
interface Sample
{
// 默认public,但不能显式地设置访问修饰符
void SayHello(); //方法
void SayYes() { Console.WriteLine(“Yes”); } //(C#8.0)方法默认实现,无;结尾
int Age { get; set; } //属性
EventHandler SizeChanged(); //事件
int this[int index] { get; set; } //索引器
}
接口类型的变量可以指向任何实现了这个接口的类的实例,这样可以灵活地指定某个实现类,而不需要改变依赖这个接口的代码,如此只能通过这些接口类型的引用调用接口的方法,如果想要调用某个实现类中自定义的、不在接口中的方法,就需要把引用强制转换为合适的类型。
基类中的实现作为接口实现
interface ISample
{
void Method1();
}
class ClassOne
{
public void Method1() { Console.WriteLine("ClassOne ISample"); }
}
class ClassTwo : ClassOne, ISample
{}
其中ClassTwo并未显式实现ISample接口中的Method1方法,但它通过继承ClassOne,ClassOne中实现了该方法
实现多个接口
当一个类实现多个接口时,实现类中要实现所有实现的接口规定的所有成员,可以使用它实现的任意接口类型来引用它的实例,但使用不同的接口类型引用,直接影响该类型的可用成员。
实现具有相同成员的接口,类可以实现多个接口,有可能在两个或更多的接口中出现具有相同签名的成员,可以提供一种实现,以供所有定义了该成员的接口共享,也可以显式地定义接口成员实现。
interface ITest1
{
void Method1();
}
interface ITest2
{
void Method1();
}
class ClassOne : ITest1, ITest2
{
//ITest1和ITest2的共同实现
public void Method1()
{
}
}
class ClassTwo : ITest1, ITest2
{
//显式地定义接口成员实现
public void ITest1.Method1()
{
}
public void ITest2.Method1()
{
}
public void NewMethod()
{
//Method1(); //编译错误
//this.Method1(); //编译错误
((ITest1)this).Method1(); //通过接口访问
//显式地定义接口成员实现的方法,实现类和其派生类都无法访问显式的接口成员实现,只能通过接口进行调用
}
参考引用
[1]: C# 权威指南
[2]: [默认实现](https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md “默认实现”)