.NET学习资料
.NET学习资料
.NET学习资料
一、接口的定义
在 C# 中,接口是一种特殊的抽象类型,它定义了一组方法签名,但不包含方法的实现。接口使用interface关键字来声明。例如,定义一个表示形状的接口IShape:
interface IShape
{
double Area();
double Perimeter();
}
在这个接口中,定义了Area和Perimeter两个方法,但没有给出具体的实现代码,这两个方法仅仅是方法签名,用于规范实现该接口的类型必须具备的行为。
二、接口的使用示例
接口不能直接实例化,需要由类或结构体来实现。下面通过一个Circle类实现IShape接口来展示其用法:
class Circle : IShape
{
private double radius;
public Circle(double radius)
{
this.radius = radius;
}
public double Area()
{
return Math.PI * radius * radius;
}
public double Perimeter()
{
return 2 * Math.PI * radius;
}
}
在上述代码中,Circle类通过: IShape语法表示实现了IShape接口,并提供了Area和Perimeter方法的具体实现。可以通过以下方式测试:
class Program
{
static void Main()
{
Circle circle = new Circle(5);
Console.WriteLine($"圆的面积: {circle.Area()}");
Console.WriteLine($"圆的周长: {circle.Perimeter()}");
}
}
这段代码创建了一个半径为 5 的圆,然后调用其实现的接口方法来计算并输出面积和周长。
三、C# 接口的特点
(一)完全抽象
接口只包含方法、属性、索引器和事件的声明,不包含任何实现代码。这使得接口成为一种纯粹的行为契约,实现接口的类型必须提供接口中所有成员的具体实现。
(二)多继承能力
C# 类不支持多重继承,但一个类可以实现多个接口。这为实现复杂的功能提供了灵活性。例如,一个类可以同时实现IComparable(用于比较)和IDisposable(用于资源释放)接口,从而具备多种不同的行为。
(三)接口成员访问修饰符
接口成员默认是公共的,并且不能使用任何访问修饰符(如public、private、protected等)来修饰。这是因为接口的目的是提供一种公共的契约,所有实现接口的类型都必须遵循这个契约。
(四)接口可以继承其他接口
一个接口可以从一个或多个其他接口继承。例如:
interface IAdvancedShape : IShape
{
void Draw();
}
这里IAdvancedShape接口继承了IShape接口,同时增加了一个Draw方法。实现IAdvancedShape接口的类型必须实现IShape接口的所有成员以及IAdvancedShape接口新增的Draw方法。
(五)接口与抽象类的区别
抽象类可以包含实现代码和抽象成员,而接口只能包含抽象成员声明:抽象类可以为某些方法提供默认实现,子类可以继承并根据需要重写这些方法;而接口的所有成员都需要由实现类型来实现。
抽象类只能被一个类继承,而一个类可以实现多个接口:这使得接口在需要实现多种不同行为时更具优势。
抽象类可以有构造函数,而接口没有构造函数:因为接口只是一种行为定义,不涉及对象的创建和初始化。
四、接口的应用场景
(一)定义通用行为
在开发框架或库时,接口常用于定义一组通用的行为。例如,在ASP.NET Core 中,IEnumerable接口定义了对集合进行迭代的行为,许多集合类型(如List、Array等)都实现了这个接口,使得它们可以在各种需要迭代的场景中统一使用。
(二)实现多态性
通过接口实现多态性,使得不同类型的对象可以根据其自身的实现来响应相同的方法调用。例如,不同的图形类(如Circle、Rectangle、Triangle等)都实现IShape接口,在需要计算图形面积或周长时,可以统一调用接口方法,而不需要关心具体的图形类型。
(三)依赖注入
在依赖注入模式中,接口起着关键作用。通过接口定义依赖关系,而不是依赖具体的实现类,可以提高代码的可测试性和可维护性。例如,在一个服务类中,通过接口依赖另一个服务,在测试时可以很容易地提供一个模拟实现来替代真实的服务。