C#属于面向对象编程,其中有三大特性封装、继承、多态。我们本次主要分析多态的实现。多态:允许不同类的对象对同一消息做出响应。实现它有两种方式,一种是编译时多态(方法重载),一种是运行时多态(方法重写)。其中运行时多态通过虚方法(virtual)和重写(override)实现。这就不免提到我们c#的三个概念:虚方法、抽象类、接口。

        注:虚方法-->抽象类-->接口。某种程度上代表着抽象概念的加深。这又不免提到我们编程的最终目标--开闭原则,关闭修改,开放拓展。我们希望软件变化时能够在不修改原来代码的基础上完成扩展达到我们的预期。我们要用抽象构建框架,用实现扩展细节。

虚方法(Virtual Methods)

在C#中,虚方法是通过virtual关键字声明的方法,允许子类通过override关键字重写该方法。虚方法提供了一种默认实现,子类可以根据需要选择是否重写。

public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal makes a sound");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Dog barks");
    }
}

  • 虚方法必须有方法体(即实现)。
  • 子类可以选择是否重写虚方法。
  • 调用时根据对象的实际类型决定执行哪个方法(动态绑定)。

抽象类(Abstract Classes)

抽象类通过abstract关键字声明,可以包含抽象方法(无实现)和普通方法。抽象类不能被实例化,只能作为基类被继承。

public abstract class Shape
{
    public abstract double CalculateArea(); // 抽象方法,无实现

    public void Display()
    {
        Console.WriteLine("This is a shape");
    }
}

public class Circle : Shape
{
    public double Radius { get; set; }

    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}

  • 抽象类可以包含抽象方法和非抽象方法。
  • 子类必须实现所有抽象方法(除非子类也是抽象类)。
  • 抽象类可以包含字段、属性、构造函数等。

接口(Interfaces)

接口通过interface关键字声明,定义了一组方法、属性或事件的契约。接口不包含实现,实现类必须提供具体的实现。

public interface IDrawable
{
    void Draw();
}

public class Rectangle : IDrawable
{
    public void Draw()
    {
        Console.WriteLine("Drawing a rectangle");
    }
}

  • 接口不能包含字段或构造函数。
  • 接口成员默认是公共的,不需要显式指定访问修饰符。
  • 一个类可以实现多个接口(C#不支持多继承,但支持多接口实现)。

比较与选择

特性 虚方法 抽象类 接口
实现 有默认实现 可包含实现 无实现
继承 单继承 单继承 多实现
实例化 可以 不可以 不可以
适用场景 提供可选重写 共享基类逻辑 定义行为契约
  • 如果需要在基类中提供默认实现,同时允许子类重写,使用虚方法。
  • 如果需要定义一组相关类的共同基类,且包含部分共享逻辑,使用抽象类。
  • 如果需要定义跨不同类层次的行为契约,使用接口。

组合使用示例

虚方法、抽象类和接口可以组合使用,以满足复杂的设计需求。

public abstract class Vehicle
{
    public abstract void Start(); // 抽象方法

    public virtual void Stop()    // 虚方法
    {
        Console.WriteLine("Vehicle stopped");
    }
}

public interface IFlyable
{
    void Fly();
}

public class Airplane : Vehicle, IFlyable
{
    public override void Start()
    {
        Console.WriteLine("Airplane started");
    }

    public void Fly()
    {
        Console.WriteLine("Airplane flying");
    }
}

更多推荐