C# 面向对象实例演示

C# 面向对象编程实例演示

一、基础概念回顾

面向对象编程(OOP)的四大基本特性:

  1. ​封装​ - 将数据和操作数据的方法绑定在一起
  2. ​继承​ - 创建新类时重用现有类的属性和方法
  3. ​多态​ - 同一操作作用于不同对象产生不同结果
  4. ​抽象​ - 简化复杂系统,只暴露必要接口

二、完整实例演示

示例1:银行账户系统

cs 复制代码
using System;

// 抽象基类 - 封装共同属性和行为
public abstract class BankAccount
{
    // 封装字段
    private string _accountNumber;
    private decimal _balance;
    
    // 属性 - 控制对字段的访问
    public string AccountNumber 
    { 
        get => _accountNumber; 
        private set => _accountNumber = value; 
    }
    
    public decimal Balance 
    { 
        get => _balance; 
        protected set => _balance = value; 
    }
    
    // 构造函数
    protected BankAccount(string accountNumber, decimal initialBalance)
    {
        AccountNumber = accountNumber;
        Balance = initialBalance;
    }
    
    // 抽象方法 - 由子类实现
    public abstract void Deposit(decimal amount);
    public abstract void Withdraw(decimal amount);
    
    // 虚方法 - 可被子类重写
    public virtual void DisplayAccountInfo()
    {
        Console.WriteLine($"账户号: {AccountNumber}");
        Console.WriteLine($"余额: {Balance:C}");
    }
}

// 派生类 - 继承并扩展功能
public class SavingsAccount : BankAccount
{
    private const decimal MinimumBalance = 100;
    private const decimal InterestRate = 0.02m;
    
    public SavingsAccount(string accountNumber, decimal initialBalance) 
        : base(accountNumber, initialBalance)
    {
        if (initialBalance < MinimumBalance)
            throw new ArgumentException("储蓄账户最低余额为100元");
    }
    
    // 实现抽象方法
    public override void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("存款金额必须大于0");
            
        Balance += amount;
        Console.WriteLine($"成功存入 {amount:C},当前余额: {Balance:C}");
    }
    
    public override void Withdraw(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("取款金额必须大于0");
            
        if (Balance - amount < MinimumBalance)
            throw new InvalidOperationException("取款后余额不能低于最低限额");
            
        Balance -= amount;
        Console.WriteLine($"成功取出 {amount:C},当前余额: {Balance:C}");
    }
    
    // 新增方法
    public void ApplyInterest()
    {
        decimal interest = Balance * InterestRate;
        Balance += interest;
        Console.WriteLine($"利息已应用: {interest:C},新余额: {Balance:C}");
    }
    
    // 重写虚方法
    public override void DisplayAccountInfo()
    {
        base.DisplayAccountInfo();
        Console.WriteLine($"账户类型: 储蓄账户");
        Console.WriteLine($"最低余额要求: {MinimumBalance:C}");
    }
}

// 另一个派生类
public class CheckingAccount : BankAccount
{
    private const decimal OverdraftLimit = -500;
    
    public CheckingAccount(string accountNumber, decimal initialBalance) 
        : base(accountNumber, initialBalance)
    {
    }
    
    public override void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("存款金额必须大于0");
            
        Balance += amount;
        Console.WriteLine($"支票账户存入 {amount:C},当前余额: {Balance:C}");
    }
    
    public override void Withdraw(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("取款金额必须大于0");
            
        if (Balance - amount < OverdraftLimit)
            throw new InvalidOperationException($"取款后余额不能低于透支限额 {OverdraftLimit:C}");
            
        Balance -= amount;
        Console.WriteLine($"支票账户取出 {amount:C},当前余额: {Balance:C}");
    }
    
    public void WriteCheck(decimal amount)
    {
        try
        {
            Withdraw(amount);
            Console.WriteLine($"已开具 {amount:C} 支票");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"开具支票失败: {ex.Message}");
        }
    }
}

// 演示类
public class BankDemo
{
    public static void Main()
    {
        // 多态 - 使用基类引用指向派生类对象
        BankAccount savings = new SavingsAccount("SAV12345", 1000);
        BankAccount checking = new CheckingAccount("CHK67890", 500);
        
        // 调用方法
        savings.Deposit(200);
        savings.Withdraw(50);
        savings.DisplayAccountInfo();
        
        Console.WriteLine("\n-----------------\n");
        
        checking.Deposit(300);
        checking.WriteCheck(100);
        checking.Withdraw(700); // 尝试透支
        checking.DisplayAccountInfo();
        
        // 使用is和as运算符
        if (savings is SavingsAccount savingsAcc)
        {
            savingsAcc.ApplyInterest();
        }
        
        BankAccount? unknownAccount = null;
        var tempAccount = unknownAccount as SavingsAccount;
        if (tempAccount == null)
        {
            Console.WriteLine("账户类型转换失败");
        }
    }
}

示例2:图形计算系统

cs 复制代码
using System;
using System.Collections.Generic;

// 接口定义
public interface IShape
{
    decimal CalculateArea();
    decimal CalculatePerimeter();
    void Draw();
}

// 具体实现类
public class Circle : IShape
{
    private decimal _radius;
    
    public Circle(decimal radius)
    {
        if (radius <= 0)
            throw new ArgumentException("半径必须大于0");
            
        _radius = radius;
    }
    
    public decimal Radius => _radius;
    
    public decimal CalculateArea() => (decimal)Math.PI * _radius * _radius;
    
    public decimal CalculatePerimeter() => 2 * (decimal)Math.PI * _radius;
    
    public void Draw()
    {
        Console.WriteLine($"绘制圆形,半径: {_radius}");
        // 实际绘图代码...
    }
}

public class Rectangle : IShape
{
    private decimal _width;
    private decimal _height;
    
    public Rectangle(decimal width, decimal height)
    {
        if (width <= 0 || height <= 0)
            throw new ArgumentException("宽度和高度必须大于0");
            
        _width = width;
        _height = height;
    }
    
    public decimal Width => _width;
    public decimal Height => _height;
    
    public decimal CalculateArea() => _width * _height;
    
    public decimal CalculatePerimeter() => 2 * (_width + _height);
    
    public void Draw()
    {
        Console.WriteLine($"绘制矩形,宽度: {_width},高度: {_height}");
        // 实际绘图代码...
    }
}

// 工厂类 - 封装对象创建逻辑
public static class ShapeFactory
{
    public static IShape CreateShape(string shapeType, params decimal[] parameters)
    {
        return shapeType.ToLower() switch
        {
            "circle" => new Circle(parameters[0]),
            "rectangle" => new Rectangle(parameters[0], parameters[1]),
            _ => throw new ArgumentException("未知的形状类型")
        };
    }
}

// 图形管理器 - 组合多个图形
public class ShapeManager
{
    private readonly List<IShape> _shapes = new();
    
    public void AddShape(IShape shape)
    {
        _shapes.Add(shape);
    }
    
    public decimal TotalArea() => _shapes.Sum(s => s.CalculateArea());
    
    public decimal TotalPerimeter() => _shapes.Sum(s => s.CalculatePerimeter());
    
    public void DrawAllShapes()
    {
        foreach (var shape in _shapes)
        {
            shape.Draw();
        }
    }
}

// 演示类
public class ShapeDemo
{
    public static void Main()
    {
        // 多态使用
        IShape circle = new Circle(5);
        IShape rectangle = new Rectangle(4, 6);
        
        Console.WriteLine($"圆形面积: {circle.CalculateArea()}");
        Console.WriteLine($"矩形周长: {rectangle.CalculatePerimeter()}");
        
        // 工厂模式使用
        IShape anotherCircle = ShapeFactory.CreateShape("circle", 3);
        IShape anotherRectangle = ShapeFactory.CreateShape("rectangle", 2, 5);
        
        // 组合模式使用
        var manager = new ShapeManager();
        manager.AddShape(circle);
        manager.AddShape(rectangle);
        manager.AddShape(anotherCircle);
        manager.AddShape(anotherRectangle);
        
        Console.WriteLine($"\n所有图形总面积: {manager.TotalArea()}");
        Console.WriteLine($"所有图形总周长: {manager.TotalPerimeter()}");
        
        Console.WriteLine("\n绘制所有图形:");
        manager.DrawAllShapes();
        
        // 接口实现检查
        if (circle is Circle c)
        {
            Console.WriteLine($"这是一个圆形,半径: {c.Radius}");
        }
        
        // 使用as运算符
        var maybeCircle = rectangle as Circle;
        if (maybeCircle == null)
        {
            Console.WriteLine("这不是一个圆形");
        }
    }
}

示例3:动物模拟系统

cs 复制代码
using System;

// 基类
public abstract class Animal
{
    // 字段封装
    private string _name;
    private int _age;
    
    // 属性
    public string Name 
    { 
        get => _name; 
        set => _name = value ?? throw new ArgumentNullException(nameof(value)); 
    }
    
    public int Age 
    { 
        get => _age; 
        protected set => _age = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(value)); 
    }
    
    // 构造函数
    protected Animal(string name, int age)
    {
        Name = name;
        Age = age;
    }
    
    // 抽象方法 - 必须由子类实现
    public abstract void MakeSound();
    
    // 虚方法 - 可被子类重写
    public virtual void Eat()
    {
        Console.WriteLine($"{Name}正在吃东西");
    }
    
    // 密封方法 - 阻止进一步重写
    public sealed override string ToString()
    {
        return $"{GetType().Name}: {Name}, {Age}岁";
    }
}

// 派生类
public class Dog : Animal
{
    public Dog(string name, int age) : base(name, age)
    {
    }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{Name}汪汪叫!");
    }
    
    // 新增方法
    public void Fetch()
    {
        Console.WriteLine($"{Name}正在捡球");
    }
}

public class Cat : Animal
{
    public Cat(string name, int age) : base(name, age)
    {
    }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{Name}喵喵叫!");
    }
    
    // 重写基类方法
    public override void Eat()
    {
        Console.WriteLine($"{Name}正在优雅地吃猫粮");
    }
    
    // 隐藏基类方法(不推荐)
    public new void ToString()
    {
        Console.WriteLine("这不会覆盖基类的ToString");
    }
}

// 接口
public interface ITrainable
{
    void Train(string command);
}

// 实现接口的类
public class PoliceDog : Dog, ITrainable
{
    public PoliceDog(string name, int age) : base(name, age)
    {
    }
    
    public void Train(string command)
    {
        Console.WriteLine($"{Name}正在接受'{command}'训练");
    }
}

// 演示类
public class AnimalDemo
{
    public static void Main()
    {
        // 多态使用
        Animal[] animals = new Animal[]
        {
            new Dog("旺财", 3),
            new Cat("咪咪", 2),
            new PoliceDog("阿黄", 5)
        };
        
        foreach (var animal in animals)
        {
            animal.MakeSound();
            animal.Eat();
            
            // 类型检查与转换
            if (animal is Dog dog)
            {
                dog.Fetch();
            }
            
            if (animal is ITrainable trainable)
            {
                trainable.Train("坐下");
            }
            
            Console.WriteLine(animal.ToString());
            Console.WriteLine();
        }
        
        // 接口实现检查
        if (animals[2] is PoliceDog policeDog)
        {
            policeDog.Train("卧倒");
        }
        
        // as运算符
        var maybeTrainable = animals[1] as ITrainable;
        if (maybeTrainable == null)
        {
            Console.WriteLine("猫不能接受训练");
        }
    }
}

三、关键概念详解

1. 封装

​优点​​:

  • 隐藏实现细节
  • 提供公共接口
  • 控制对数据的访问

​示例​​:

cs 复制代码
public class Person
{
    // 私有字段
    private string _ssn;
    
    // 公共属性 - 控制访问
    public string SSN
    {
        get => _ssn;
        set
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentException("SSN不能为空");
                
            if (value.Length != 9)
                throw new ArgumentException("SSN必须是9位");
                
            _ssn = value;
        }
    }
    
    // 只读属性
    public int Age { get; private set; }
    
    // 构造函数初始化
    public Person(string ssn, int age)
    {
        SSN = ssn;
        Age = age;
    }
    
    // 方法封装行为
    public void HaveBirthday()
    {
        Age++;
        Console.WriteLine($"生日快乐!现在是{Age}岁");
    }
}

2. 继承

​语法​​:

cs 复制代码
public class BaseClass
{
    // 基类成员
}

public class DerivedClass : BaseClass
{
    // 派生类成员
}

​示例​​:

cs 复制代码
public class Vehicle
{
    public string Make { get; set; }
    public string Model { get; set; }
    
    public virtual void Start()
    {
        Console.WriteLine("车辆启动");
    }
}

public class Car : Vehicle
{
    public int DoorCount { get; set; }
    
    public override void Start()
    {
        Console.WriteLine("汽车启动");
        base.Start(); // 调用基类方法
    }
    
    public void Honk()
    {
        Console.WriteLine("喇叭响");
    }
}

3. 多态

​实现方式​​:

  1. 方法重写(override)
  2. 接口实现
  3. 抽象方法

​示例​​:

cs 复制代码
public interface IShape
{
    decimal Area();
}

public class Circle : IShape
{
    public decimal Radius { get; set; }
    
    public decimal Area() => (decimal)Math.PI * Radius * Radius;
}

public class Rectangle : IShape
{
    public decimal Width { get; set; }
    public decimal Height { get; set; }
    
    public decimal Area() => Width * Height;
}

// 使用
IShape[] shapes = new IShape[]
{
    new Circle { Radius = 5 },
    new Rectangle { Width = 4, Height = 6 }
};

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

4. 抽象

​抽象类​​:

cs 复制代码
public abstract class Animal
{
    public abstract void MakeSound(); // 必须由子类实现
    
    public virtual void Eat() // 可选实现
    {
        Console.WriteLine("动物在吃东西");
    }
}

​接口​​:

cs 复制代码
public interface IDriveable
{
    void Drive();
    int MaxSpeed { get; set; }
}

​示例​​:

cs 复制代码
public abstract class Shape
{
    public abstract decimal CalculateArea();
    
    public virtual void Display()
    {
        Console.WriteLine("这是一个形状");
    }
}

public class Triangle : Shape
{
    public decimal Base { get; set; }
    public decimal Height { get; set; }
    
    public override decimal CalculateArea()
    {
        return Base * Height / 2;
    }
    
    public new void Display() // 隐藏基类方法(不推荐)
    {
        Console.WriteLine("这是一个三角形");
    }
}

四、设计模式示例

1. 工厂模式

cs 复制代码
public interface IWeapon
{
    void Attack();
}

public class Sword : IWeapon
{
    public void Attack() => Console.WriteLine("挥剑攻击");
}

public class Bow : IWeapon
{
    public void Attack() => Console.WriteLine("拉弓射箭");
}

public static class WeaponFactory
{
    public static IWeapon CreateWeapon(string weaponType)
    {
        return weaponType.ToLower() switch
        {
            "sword" => new Sword(),
            "bow" => new Bow(),
            _ => throw new ArgumentException("未知武器类型")
        };
    }
}

// 使用
IWeapon weapon = WeaponFactory.CreateWeapon("sword");
weapon.Attack();

2. 单例模式

cs 复制代码
public sealed class Logger
{
    private static readonly Lazy<Logger> _instance = 
        new Lazy<Logger>(() => new Logger());
    
    public static Logger Instance => _instance.Value;
    
    private Logger() { }
    
    public void Log(string message)
    {
        Console.WriteLine($"[{DateTime.Now}] {message}");
    }
}

// 使用
Logger.Instance.Log("系统启动");

3. 观察者模式

cs 复制代码
public interface IObserver
{
    void Update(string message);
}

public class NewsAgency
{
    private readonly List<IObserver> _observers = new();
    
    public void AddObserver(IObserver observer)
    {
        _observers.Add(observer);
    }
    
    public void RemoveObserver(IObserver observer)
    {
        _observers.Remove(observer);
    }
    
    public void PublishNews(string news)
    {
        foreach (var observer in _observers)
        {
            observer.Update(news);
        }
    }
}

public class Subscriber : IObserver
{
    public string Name { get; }
    
    public Subscriber(string name)
    {
        Name = name;
    }
    
    public void Update(string message)
    {
        Console.WriteLine($"{Name}收到新闻: {message}");
    }
}

// 使用
var agency = new NewsAgency();
agency.AddObserver(new Subscriber("张三"));
agency.AddObserver(new Subscriber("李四"));

agency.PublishNews("股市今日大涨");

五、最佳实践

  1. ​优先使用组合而非继承​​:

    cs 复制代码
    // 更好的设计 - 使用组合
    public class Engine { }
    
    public class Car
    {
        public Engine Engine { get; } = new Engine();
    }
  2. ​遵循SOLID原则​​:

    • 单一职责原则(SRP)
    • 开闭原则(OCP)
    • 里氏替换原则(LSP)
    • 接口隔离原则(ISP)
    • 依赖倒置原则(DIP)
  3. ​合理使用访问修饰符​​:

    cs 复制代码
    public class MyClass
    {
        public int PublicField; // 慎用
        protected int ProtectedField;
        internal int InternalField;
        protected internal int ProtectedInternalField;
        private int _privateField; // 推荐
    }
  4. ​避免过度使用继承​​:

    • 继承层次不要太深(通常不超过3层)
    • 考虑使用接口或组合替代
  5. ​使用属性而非公共字段​​:

    cs 复制代码
    // 不推荐
    public class BadDesign
    {
        public int Value;
    }
    
    // 推荐
    public class GoodDesign
    {
        private int _value;
        
        public int Value
        {
            get => _value;
            set => _value = value > 0 ? value : throw new ArgumentOutOfRangeException();
        }
    }
  6. ​实现IDisposable接口管理资源​​:

    cs 复制代码
    public class ResourceHolder : IDisposable
    {
        private bool _disposed = false;
        private FileStream _fileStream;
        
        public ResourceHolder(string path)
        {
            _fileStream = new FileStream(path, FileMode.Open);
        }
        
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _fileStream?.Dispose();
                }
                
                _disposed = true;
            }
        }
        
        ~ResourceHolder() => Dispose(false);
    }

通过以上实例和最佳实践,您可以更好地理解和应用C#的面向对象编程特性,编写出更健壮、可维护和可扩展的代码。

相关推荐
冰茶_5 小时前
WPF之RadioButton控件详解
学习·microsoft·c#·wpf
开开心心就好11 小时前
无限制文本转语音解决方案
开发语言·人工智能·macos·微信·pdf·c#·语音识别
Envyᥫᩣ15 小时前
C#中的LINQ:简化数据查询与操作
开发语言·c#·linq
王维志15 小时前
浅谈C# record关键字
后端·c#·asp.net
冰茶_15 小时前
WPF之Image控件详解
学习·microsoft·微软·c#·wpf·wpf控件
大飞pkz17 小时前
【Unity】MVP框架的使用例子
unity·c#·mvc·框架·mvp·ui框架
电商api接口开发19 小时前
ASP.NET MVC 入门与提高指南六
c#·asp.net·mvc
宝桥南山20 小时前
Azure Devops - 尝试一下在Pipeline中使用Self-hosted Windows agent
microsoft·微软·c#·.netcore·azure·devops
冰茶_1 天前
WPF之TextBox控件详解
学习·microsoft·微软·c#·wpf