C# 之封装、继承与多态详解

C# 封装、继承与多态详解

面向对象编程有三大核心特性:封装继承多态,它们构成了OOP的重要基础。下面我将从理论到实践全面解析这三大特性在C#中的实现与应用。

一、封装(Encapsulation)

1. 封装的概念与实现

封装是指将数据(字段)和操作数据的方法(属性/方法)绑定在一起的技术。C#通过访问修饰符实现封装:

public class BankAccount
{
    // 私有字段(封装数据)
    private string _accountNumber;
    private decimal _balance;
    private DateTime _createdDate;

    // 公开属性(控制访问)
    public string AccountNumber 
    {
        get => _accountNumber;
        private set => _accountNumber = value;
    }

    public decimal Balance 
    {
        get => _balance;
        private set
        {
            if (value < 0)
                throw new ArgumentException("余额不能为负");
            _balance = value;
        }
    }

    // 构造方法
    public BankAccount(string accountNumber)
    {
        AccountNumber = accountNumber;
        _createdDate = DateTime.Now;
    }

    // 公开方法(封装业务逻辑)
    public void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("存款金额必须大于零");
      
        Balance += amount;
        LogTransaction($"存入 {amount}");
    }

    // 私有方法(实现细节隐藏)
    private void LogTransaction(string message)
    {
        Console.WriteLine($"[{DateTime.Now}] {message}");
    }
}

2. 封装的五大优势

  1. 数据保护:防止对象数据被非法访问或修改
  2. 实现隐藏:隐藏类的实现细节,仅暴露必要接口
  3. 灵活性:内部修改不影响外部调用
  4. 易于维护:修改实现不需要改变接口
  5. 降低耦合:减少类之间的依赖

3. 访问修饰符总结

修饰符类内部派生类同一程序集其他程序集
public
private
protected
internal
protected internal仅派生类

二、继承(Inheritance)

1. 继承的基础语法

// 基类(父类)
public class Animal
{
    public string Name { get; set; }
    public int Age { get; set; }

    public virtual void MakeSound()
    {
        Console.WriteLine("动物发出声音");
    }

    public void Eat()
    {
        Console.WriteLine("正在进食...");
    }
}

// 派生类(子类)
public class Dog : Animal
{
    public string Breed { get; set; }

    // 方法重写
    public override void MakeSound()
    {
        Console.WriteLine("汪汪汪!");
    }

    // 新增方法
    public void Fetch()
    {
        Console.WriteLine($"{Name}正在捡球");
    }
}

// 使用
Dog myDog = new Dog { Name = "Buddy", Breed = "金毛" };
myDog.MakeSound();  // 输出"汪汪汪!"
myDog.Eat();        // 继承自Animal的方法

2. 继承中的关键概念

  • base关键字:访问基类成员
public class Cat : Animal
{
    public override void MakeSound()
    {
        base.MakeSound();  // 先调用父类实现
        Console.WriteLine("喵喵喵!");
    }
}
  • protected访问:允许子类访问
public class BaseClass
{
    protected int _protectedValue = 10;
}

public class DerivedClass : BaseClass
{
    public void AccessProtected()
    {
        Console.WriteLine(_protectedValue);  // 可以访问
    }
}

3. 继承的五个特点

  1. 单继承:C#只支持单继承(一个类只能继承一个父类)
  2. 传递性:继承关系可以传递(A→B→C)
  3. 复用性:子类自动获得父类的非private成员
  4. 扩展性:子类可以添加新成员或重写父类方法
  5. 构造顺序:先调用父类构造函数,再调用子类构造函数

三、多态(Polymorphism)

1. 多态的基本实现

public abstract class Shape
{
    public abstract double Area();  // 抽象方法
    public virtual void Draw()      // 虚方法
    {
        Console.WriteLine("绘制形状");
    }
}

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

    public override double Area() => Math.PI * Radius * Radius;

    public override void Draw()
    {
        Console.WriteLine("绘制圆形 ○");
    }
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public override double Area() => Width * Height;
  
    // 未重写Draw方法,使用父类实现
}

// 使用多态
List<Shape> shapes = new List<Shape>
{
    new Circle { Radius = 5 },
    new Rectangle { Width = 4, Height = 6 }
};

foreach (var shape in shapes)
{
    shape.Draw();
    Console.WriteLine($"面积: {shape.Area()}");
}

2. 多态的三种形式

  1. 方法重写(Override)

    • 使用virtual声明可重写方法
    • 使用override重写父类方法
  2. 抽象类与抽象方法

    public abstract class DatabaseConnection
    {
        public abstract void Open();
        public abstract void Close();
      
        public string ConnectionString { get; set; }
    }
    
    public class SqlConnection : DatabaseConnection
    {
        public override void Open() {/* SQL连接实现 */}
        public override void Close() {/* SQL关闭实现 */}
    }
    
  3. 接口实现

    public interface ILogger
    {
        void Log(string message);
    }
    
    public class FileLogger : ILogger
    {
        public void Log(string message) {/* 写入文件 */}
    }
    
    public class ConsoleLogger : ILogger
    {
        public void Log(string message) { Console.WriteLine(message); }
    }
    

3. 多态的四大优势

  1. 代码可扩展:易于添加新类型而无需修改现有代码
  2. 接口统一:不同对象通过统一接口操作
  3. 运行时分派:根据实际对象类型调用对应方法
  4. 程序解耦:降低模块间的依赖关系

四、综合应用示例:图形编辑器

// 基类
public abstract class Graphic
{
    public int X { get; set; }
    public int Y { get; set; }
    public ConsoleColor Color { get; set; }
  
    public abstract void Draw();
    public virtual void Move(int deltaX, int deltaY)
    {
        X += deltaX;
        Y += deltaY;
    }
}

// 派生类
public class Line : Graphic
{
    public int EndX { get; set; }
    public int EndY { get; set; }
  
    public override void Draw()
    {
        Console.ForegroundColor = Color;
        Console.WriteLine($"在({X},{Y})到({EndX},{EndY})绘制线段");
        Console.ResetColor();
    }
}

public class Circle : Graphic
{
    public int Radius { get; set; }
  
    public override void Draw()
    {
        Console.ForegroundColor = Color;
        Console.WriteLine($"以({X},{Y})为中心绘制半径为{Radius}的圆");
        Console.ResetColor();
    }
}

// 使用多态
Graphic[] graphics = new Graphic[]
{
    new Line { X=10, Y=10, EndX=50, EndY=50, Color=ConsoleColor.Red },
    new Circle { X=30, Y=30, Radius=20, Color=ConsoleColor.Blue }
};

foreach (var g in graphics)
{
    g.Draw();       // 多态调用
    g.Move(5, 5);   // 调用继承的方法
}

五、关键注意事项

  1. 何时使用继承?

    • 符合"is-a"关系时才使用继承
    • 当需要利用多态行为时
    • 当多个类共享大量共性代码时
  2. 何时使用组合?

    • "has-a"关系优先使用组合
    public class Car
    {
        private Engine _engine;  // 组合优于继承
        private List<Wheel> _wheels;
    }
    
  3. 最佳实践

    • 尽量减少继承层级(通常不超过3层)
    • 优先选择sealed类防止非预期继承
    • 避免使用protected字段(改用protected属性)
    • 使用抽象类定义接口的默认实现
    • 为多态基类考虑定义抽象方法而非虚方法

掌握封装、继承与多态这三大特性,是成为优秀C#程序员的关键。理解这些概念不仅有助于编写更优雅的代码,还能设计出更灵活、更易扩展的软件架构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X-Vision

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值