在C# 8.0及更高版本中,引入了默认接口方法这一特性,它允许接口包含默认实现的方法。这一特性不仅增强了多态,还促进了代码复用,使得接口的实现更加灵活。本文将深入探讨默认接口方法的核心概念、使用场景、最佳实践以及一些高级技巧。
默认接口方法的基本概念
默认接口方法是接口中带有实现的普通方法。它们允许接口作者提供一些“默认行为”,实现类可以选择使用这些默认行为,或者覆盖它们以提供自定义行为。
关键概念
- 默认实现:接口提供的实现,实现类可以选择使用或覆盖。
- 多态:实现类可以表现出不同的行为,即使它们都实现了相同的接口。
- 代码复用:默认实现促进了代码复用,减少了重复代码。
使用场景
场景1:提供通用的实现
当接口的实现类通常以相同的方式执行某些操作时,可以在接口中提供默认实现。
场景2:增强旧接口
在不破坏现有实现的情况下,为旧接口添加新方法。
场景3:实现算法的可选变体
为算法提供默认实现,同时允许实现类提供特定情况下的变体。
示例代码
定义一个接口与默认方法
代码语言:javascript复制public interface IShape
{
double CalculateArea();
default double CalculatePerimeter() => Math.Sqrt(Area() * 4); // 假设面积是边长平方
}
实现接口
代码语言:javascript复制public class Circle : IShape
{
public double Radius { get; }
public Circle(double radius) => Radius = radius;
public double CalculateArea() => Math.PI * Radius * Radius;
}
public class Rectangle : IShape
{
public double Width { get; }
public double Height { get; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public double CalculateArea() => Width * Height;
// 覆盖默认方法
public override double CalculatePerimeter() => 2 * (Width Height);
}
高级应用
条件成员
默认接口方法可以是条件成员,这意味着它们可以访问this
或实现类中的其他成员。
public interface IShape
{
double Area { get; }
default public double CalculatePerimeter() => Math.Sqrt(Area * 4);
}
虚拟方法和重写
默认接口方法可以被标记为virtual
,并且可以在实现类中被重写。
public interface IShape
{
double Area { get; }
virtual double CalculatePerimeter() => Math.Sqrt(Area * 4);
}
public class Circle : IShape
{
public double Radius { get; }
public Circle(double radius) => Radius = radius;
public double Area => Math.PI * Radius * Radius;
// 重写默认方法
public override double CalculatePerimeter() => 2 * Math.PI * Radius;
}
接口继承
默认接口方法可以被接口继承,子接口可以提供自己的默认实现。
代码语言:javascript复制public interface IShape
{
double Area { get; }
double CalculatePerimeter();
}
public interface ICircle : IShape
{
double Radius { get; }
default double Area => Math.PI * Radius * Radius;
default double CalculatePerimeter() => 2 * Math.PI * Radius;
}
性能考虑
虽然默认接口方法提供了极大的灵活性,但它们也可能引入一些性能开销。例如,虚拟默认接口方法可能会增加方法调用的开销。因此,在性能敏感的应用中,应谨慎使用默认接口方法。