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 编译时 特殊场景(不推荐,易混淆)

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

相关推荐
晨晖26 小时前
MyBatisPlus的条件构造器
java·数据库·windows
有味道的男人6 小时前
速卖通商品详情接口(速卖通API系列)
java·大数据·数据库
一只小透明啊啊啊啊6 小时前
垃圾回收算法有哪些
java·jvm
DanB246 小时前
Java(网络编程)
java·网络·php
5***84646 小时前
Spring全家桶简介
java·后端·spring
u***1376 小时前
Tomcat的server.xml配置详解
xml·java·tomcat
张人玉6 小时前
Prism 框架笔记及实例
c#·wpf·prism
花阴偷移6 小时前
kotlin语法(上)
android·java·开发语言·kotlin
木易 士心6 小时前
Go、Rust、Kotlin、Python 与 Java 从性能到生态,全面解读五大主流编程语言
java·golang·rust
qq_336313936 小时前
java基础-set系列集合
java·开发语言·python