C# 基础——多态的实现方式

在C#中,多态(Polymorphism)是面向对象编程的核心特性之一,指"同一操作作用于不同对象时,可产生不同的执行结果"。其本质是通过统一的接口(或基类)调用不同实现,实现代码的灵活性和可扩展性。

C#中多态的实现方式主要有以下4种,核心是基于动态绑定(运行时确定具体调用的方法)静态绑定(编译时确定)

1. 继承+虚方法重写(virtual + override)

这是最常用的动态多态实现方式,通过基类定义虚方法,派生类重写该方法,最终通过基类引用调用时,会自动执行派生类的实现。

实现步骤:
  • 基类中用 virtual 关键字声明方法(含默认实现);
  • 派生类中用 override 关键字重写该方法(提供自定义实现);
  • 通过基类引用指向派生类对象,调用方法时自动执行派生类的重写版本。
示例代码:
csharp 复制代码
// 基类
public class Animal {
    // 虚方法:定义统一接口,提供默认实现
    public virtual void Speak() {
        Console.WriteLine("动物发出声音");
    }
}

// 派生类1:重写虚方法
public class Dog : Animal {
    public override void Speak() {
        Console.WriteLine("狗叫:汪汪");
    }
}

// 派生类2:重写虚方法
public class Cat : Animal {
    public override void Speak() {
        Console.WriteLine("猫叫:喵喵");
    }
}

// 调用:多态体现
class Program {
    static void Main() {
        Animal animal1 = new Dog(); // 基类引用指向派生类对象
        Animal animal2 = new Cat();
        
        animal1.Speak(); // 输出:狗叫:汪汪(执行Dog的实现)
        animal2.Speak(); // 输出:猫叫:喵喵(执行Cat的实现)
    }
}
特点:
  • 动态绑定:运行时根据对象实际类型确定调用的方法;
  • 基类有默认实现,派生类可选择是否重写(不重写则沿用基类逻辑)。

2. 抽象类+抽象方法(abstract)

抽象类是无法实例化的基类,其中的抽象方法(abstract没有默认实现,必须由派生类强制重写。通过抽象类引用调用方法时,同样会执行派生类的实现,属于动态多态。

实现步骤:
  • abstract 关键字定义抽象类;
  • 抽象类中用 abstract 声明抽象方法(只有签名,无方法体);
  • 派生类必须用 override 重写所有抽象方法;
  • 通过抽象类引用指向派生类对象,调用方法时执行派生类实现。
示例代码:
csharp 复制代码
// 抽象基类(无法实例化)
public abstract class Shape {
    // 抽象方法:必须由派生类实现
    public abstract double GetArea();
}

// 派生类1:实现抽象方法
public class Circle : Shape {
    public double Radius { get; set; }
    public Circle(double radius) => Radius = radius;
    
    public override double GetArea() {
        return Math.PI * Radius * Radius; // 圆面积公式
    }
}

// 派生类2:实现抽象方法
public class Rectangle : Shape {
    public double Width { get; set; }
    public double Height { get; set; }
    public Rectangle(double w, double h) {
        Width = w;
        Height = h;
    }
    
    public override double GetArea() {
        return Width * Height; // 矩形面积公式
    }
}

// 调用:多态体现
class Program {
    static void Main() {
        Shape shape1 = new Circle(2); // 抽象类引用指向派生类
        Shape shape2 = new Rectangle(3, 4);
        
        Console.WriteLine(shape1.GetArea()); // 输出:12.566...(圆面积)
        Console.WriteLine(shape2.GetArea()); // 输出:12(矩形面积)
    }
}
特点:
  • 动态绑定:运行时确定调用的方法;
  • 强制派生类实现抽象方法(避免"忘记重写"的错误);
  • 抽象类可包含非抽象方法(提供默认实现)。

3. 接口实现(interface)

接口是一种"行为契约",仅定义方法签名(无实现),类通过 implements 关键字实现接口时,必须实现接口的所有方法。不同类可实现同一接口的不同逻辑,通过接口引用调用时体现多态。

实现步骤:
  • interface 关键字定义接口(方法无访问修饰符,默认public);
  • 类用 : 接口名 实现接口,并实现所有接口方法;
  • 通过接口引用指向实现类对象,调用方法时执行对应类的实现。
示例代码:
csharp 复制代码
// 接口:定义行为契约
public interface IFlyable {
    void Fly(); // 仅声明,无实现
}

// 实现类1:鸟
public class Bird : IFlyable {
    public void Fly() {
        Console.WriteLine("鸟扇动翅膀飞行");
    }
}

// 实现类2:飞机
public class Plane : IFlyable {
    public void Fly() {
        Console.WriteLine("飞机靠引擎飞行");
    }
}

// 调用:多态体现
class Program {
    static void Main() {
        IFlyable flyer1 = new Bird(); // 接口引用指向实现类
        IFlyable flyer2 = new Plane();
        
        flyer1.Fly(); // 输出:鸟扇动翅膀飞行
        flyer2.Fly(); // 输出:飞机靠引擎飞行
    }
}
特点:
  • 动态绑定:运行时确定调用的方法;
  • 接口支持"多实现"(一个类可实现多个接口),而类只能单继承,因此接口更灵活;
  • 适合定义跨类别的通用行为(如"飞行"可被鸟、飞机等不同类型的类实现)。

4. 隐藏基类方法(new关键字)

通过 new 关键字在派生类中定义与基类同名的方法,会"隐藏"基类方法(而非重写)。这种方式属于静态多态(编译时绑定),调用哪个版本的方法由"引用类型"而非"对象实际类型"决定。

实现步骤:
  • 基类定义普通方法;
  • 派生类用 new 关键字定义同名方法(隐藏基类方法);
  • 调用时,基类引用调用基类方法,派生类引用调用派生类方法。
示例代码:
csharp 复制代码
public class Parent {
    public void Print() {
        Console.WriteLine("父类方法");
    }
}

public class Child : Parent {
    // new关键字:隐藏父类的Print方法
    public new void Print() {
        Console.WriteLine("子类方法");
    }
}

class Program {
    static void Main() {
        Parent p = new Child(); // 基类引用指向派生类对象
        Child c = new Child();  // 派生类引用
        
        p.Print(); // 输出:父类方法(由引用类型Parent决定)
        c.Print(); // 输出:子类方法(由引用类型Child决定)
    }
}
注意:
  • 这不是"真正的多态",因为行为由引用类型(编译时已知)决定,而非对象实际类型;
  • 通常不推荐使用,容易导致逻辑混淆(建议优先用 override 重写)。

总结:多态实现方式的对比

方式 核心关键字 绑定时机 适用场景
虚方法重写 virtual + override 运行时 基类有默认实现,派生类可选择性重写
抽象类+抽象方法 abstract + override 运行时 基类无默认实现,强制派生类提供具体逻辑
接口实现 interface 运行时 跨类别的行为约定,支持多实现
隐藏基类方法 new 编译时 特殊场景(不推荐,易混淆)

实际开发中,接口实现虚方法重写是最常用的多态方式,它们通过动态绑定实现了"统一接口,不同实现",大幅提升了代码的扩展性和可维护性。

相关推荐
CodeCraft Studio3 小时前
PDF处理控件Aspose.PDF教程:在C#中将PDF转换为Base64
服务器·pdf·c#·.net·aspose·aspose.pdf·pdf转base64
小咕聊编程4 小时前
【含文档+PPT+源码】基于spring boot的固定资产管理系统
java·spring boot·后端
roykingw4 小时前
【终极面试集锦】如何设计微服务熔断体系?
java·微服务·面试
我命由我123454 小时前
Spring Cloud - Spring Cloud 微服务概述 (微服务的产生与特点、微服务的优缺点、微服务设计原则、微服务架构的核心组件)
java·运维·spring·spring cloud·微服务·架构·java-ee
それども4 小时前
忽略Lombok构建警告
java·开发语言·jvm
用户68545375977694 小时前
🎮 Java设计模式:从青铜到王者的代码修炼手册
java·后端
马尚道4 小时前
Java高手速成--吃透源码+手写组件+定制开发教程
java
我命由我123454 小时前
Spring Cloud - Spring Cloud 注册中心与服务提供者(Spring Cloud Eureka 概述、微服务快速入门、微服务应用实例)
java·spring boot·spring·spring cloud·微服务·eureka·java-ee
MetaverseMan4 小时前
Java Spring 框架的`@Autowired` 注解 以及依赖注入分析
java·开发语言·spring