在 C# 中,接口和抽象类都是面向对象编程的基础支柱,使我们能够为类定义协定和共享行为。但是什么时候应该使用接口,什么时候抽象类是更好的选择呢?了解这两个概念的细微差别是编写灵活、可维护且可扩展的 C# 代码的关键。在本文中,我们将探讨接口和抽象类之间的区别,并为您提供有关如何有效使用它们的实用见解。
接口的核心是定义任何实现类都必须遵循的协定。这是一种指定类应该执行哪些操作的方法,而无需规定如何实现这些操作。将其视为类的蓝图。
public interface IShape
{
double CalculateArea();
double CalculatePerimeter();
}
此处,接口定义了两个方法,即 .实现此接口的任何类都需要为这些方法提供自己的实现。IShapeCalculateAreaCalculatePerimeter
public class Circle : IShape
{
public double Radius { get; set; }
public double CalculateArea()
{
return Math.PI * Math.Pow(Radius, 2);
}
public double CalculatePerimeter()
{
return 2 * Math.PI * Radius;
}
}
该类实现接口并提供自己的 and 版本。如果我们稍后添加一个类,它可以实现相同的接口,但具有不同的实现。CircleIShapeCalculateAreaCalculatePerimeterRectangle
抽象类允许我们定义派生类的实现和契约。它可以包含抽象方法 (无 implementation) 和非抽象方法 (有 implementation)。当您想在不同类之间共享一些通用功能,但仍为特定实现留出空间时,这使其成为理想的选择。
public abstract class Shape
{
public abstract double CalculateArea();
public void DisplayShapeType()
{
Console.WriteLine("This is a shape.");
}
}
在这里,抽象类声明了一个抽象方法,该方法必须由任何派生类实现。它还提供了一个完全实现的方法,可供所有子类使用。ShapeCalculateAreaDisplayShapeType
public class Rectangle : Shape
{
public double Length { get; set; }
public double Width { get; set; }
public override double CalculateArea()
{
return Length * Width;
}
}
在这里,该类派生自抽象类,并且是实现该方法所必需的。但是,它无需重新实现即可继承该方法。RectangleShapeCalculateAreaDisplayShapeType
现在,让我们分解一下接口和抽象类之间的一些关键区别,帮助您确定何时使用每个接口:
2. 实施:
3. 继承:
4. 字段和属性:
2. 不相关的类:当类不属于同一继承层次结构但需要执行类似的操作时,接口有助于将它们统一在一个公共契约下。
2. 基本功能:当您需要一个基类来提供基础功能,同时仍然强制执行某些方法覆盖时。
将抽象类和接口组合在一起以获得两者的好处也很常见。您可以定义一个实现一个或多个接口的抽象类,然后具体类可以从抽象类派生,同时仍然遵守接口协定。
public interface IMovable
{
void Move();
}
public abstract class Vehicle : IMovable
{
public void Move()
{
Console.WriteLine("The vehicle is moving.");
}
public abstract void Refuel();
}
public class Car : Vehicle
{
public override void Refuel()
{
Console.WriteLine("Refueling the car.");
}
}
在这里,抽象类实现了接口,但也定义了自己的抽象方法 。该类必须实现,但免费获取该方法。VehicleIMovableRefuelCarRefuelMove
在 C# 中的接口和抽象类之间进行选择归根结底是要了解设计的具体要求。如果你正在创建一个多个不相关的类应该遵守的 Contract,请选择 interfaces。如果您需要在相关类之间共享通用功能,同时仍然强制执行一些类似 Contract 的行为,那么抽象类是您的朋友。