面向对象编程

目录

03. 面向对象编程

C#面向对象编程完全指南 - 从C++到C#的OOP对比学习


📌 本章导航


类和对象

类定义基础

C#的类定义与C++有很多相似之处,但也有一些重要的差异:

// C#类定义
public class Player
{
    // 字段 (成员变量)
    private string name;
    private int level;
    private int health;
    
    // 属性 (类似C++的getter/setter)
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
    
    public int Level
    {
        get { return level; }
        set { level = value > 0 ? value : 1; }  // 验证逻辑
    }
    
    public int Health
    {
        get { return health; }
        set { health = Math.Clamp(value, 0, 100); }  // 使用内置方法
    }
    
    // 构造函数
    public Player(string name)
    {
        this.name = name;
        level = 1;
        health = 100;
    }
    
    // 方法
    public void TakeDamage(int damage)
    {
        health = Math.Max(0, health - damage);
        if (health <= 0)
        {
            OnDeath();
        }
    }
    
    public void LevelUp()
    {
        level++;
        health = 100;  // 升级时恢复生命
    }
    
    private void OnDeath()
    {
        Console.WriteLine($"{name} died!");
    }
}

// 对象创建和使用
Player player = new Player("Hero");
player.TakeDamage(20);
player.LevelUp();
Console.WriteLine($"Player: {player.Name}, Level: {player.Level}, Health: {player.Health}");

与C++类定义的对比

特性 C++ C# 说明
类声明 class Player { ... }; public class Player { ... } C#需要访问修饰符
构造函数 Player(const string& name) public Player(string name) C#需要访问修饰符
析构函数 ~Player() ~Player() (不推荐) C#有GC,通常不需要析构函数
成员访问 player.name (public) player.Name (属性) C#推荐使用属性

C#特有的类特性

// 部分类 (partial class)
public partial class GameEntity
{
    public string Name { get; set; }
}

public partial class GameEntity
{
    public void Initialize()
    {
        // 可以在不同文件中定义同一类的不同部分
    }
}

// 静态类 (不能实例化)
public static class GameMath
{
    public static float CalculateDistance(Vector3 a, Vector3 b)
    {
        return Vector3.Distance(a, b);
    }
    
    public static int CalculateScore(int baseScore, float multiplier)
    {
        return (int)(baseScore * multiplier);
    }
}

// 密封类 (不能被继承)
public sealed class SingletonManager
{
    private static SingletonManager instance;
    
    private SingletonManager() { }
    
    public static SingletonManager Instance
    {
        get
        {
            if (instance == null)
                instance = new SingletonManager();
            return instance;
        }
    }
}

属性和字段

字段 (Fields)

字段是类的成员变量,在C#中通常声明为私有:

public class GameItem
{
    // 私有字段 (类似C++的private成员变量)
    private string name;
    private int value;
    private bool isEquipped;
    
    // 只读字段 (类似C++的const成员)
    private readonly int id;
    private static readonly string defaultCategory = "Misc";
    
    public GameItem(string name, int value)
    {
        this.name = name;
        this.value = value;
        this.id = GenerateId();  // 只能在构造函数中赋值
    }
    
    private int GenerateId()
    {
        return new Random().Next(1000, 9999);
    }
    
    // 公共字段 (不推荐,但有时有用)
    public const int MAX_STACK_SIZE = 99;
}

属性 (Properties)

属性是C#的特色功能,提供了更安全的数据访问方式:

public class Character
{
    // 私有字段
    private int health;
    private int maxHealth;
    private string characterClass;
    
    // 自动属性 (C# 3.0+)
    public string Name { get; set; }
    public int Level { get; set; } = 1;  // 带默认值
    
    // 完整属性 (带验证逻辑)
    public int Health
    {
        get { return health; }
        set 
        { 
            health = Math.Clamp(value, 0, MaxHealth);
            OnHealthChanged();
        }
    }
    
    // 只读属性
    public int MaxHealth
    {
        get { return maxHealth; }
        private set { maxHealth = value; }  // private setter
    }
    
    // 计算属性
    public bool IsAlive => Health > 0;
    public float HealthPercentage => (float)Health / MaxHealth * 100;
    
    // 索引器 (类似C++的operator[])
    private Dictionary<string, int> stats = new Dictionary<string, int>();
    public int this[string statName]
    {
        get { return stats.ContainsKey(statName) ? stats[statName] : 0; }
        set { stats[statName] = value; }
    }
    
    // 只读索引器 (C# 8.0+)
    public int this[int index] => stats.Values.ElementAtOrDefault(index);
    
    private void OnHealthChanged()
    {
        if (Health <= 0)
        {
            Console.WriteLine("Character died!");
        }
    }
    
    public Character(string name, int maxHealth = 100)
    {
        Name = name;
        this.maxHealth = maxHealth;
        this.health = maxHealth;
    }
}

// 使用示例
Character player = new Character("Warrior", 150);
player.Health = 50;  // 调用setter
Console.WriteLine($"Health: {player.Health}");  // 调用getter
Console.WriteLine($"Alive: {player.IsAlive}");  // 计算属性
player["strength"] = 10;  // 索引器

属性 vs 字段的对比

public class PlayerStats
{
    // C++风格: 直接访问字段
    // private int health;  // C++中可能直接访问
    
    // C#风格: 使用属性控制访问
    private int _health = 100;
    private int _maxHealth = 100;
    
    public int Health
    {
        get { return _health; }
        set 
        { 
            _health = Math.Clamp(value, 0, _maxHealth);
            if (_health <= 0)
            {
                OnPlayerDied();
            }
        }
    }
    
    public int MaxHealth
    {
        get { return _maxHealth; }
        set 
        { 
            _maxHealth = Math.Max(1, value);
            _health = Math.Min(_health, _maxHealth);  // 确保健康值不超过最大值
        }
    }
    
    // 只读属性
    public float HealthPercentage => (float)_health / _maxHealth * 100;
    
    // 条件属性
    public bool IsInCombat { get; set; }
    public bool CanLevelUp => HealthPercentage >= 80 && IsInCombat;
    
    private void OnPlayerDied()
    {
        Console.WriteLine("Player has died!");
        // 触发死亡事件
    }
}

构造函数

构造函数类型

public class GameEntity
{
    public string Name { get; set; }
    public int Id { get; private set; }
    public Vector3 Position { get; set; }
    public float Rotation { get; set; }
    
    // 无参构造函数
    public GameEntity()
    {
        Name = "Default";
        Id = GenerateId();
        Position = Vector3.zero;
        Rotation = 0f;
    }
    
    // 有参构造函数
    public GameEntity(string name)
    {
        Name = name;
        Id = GenerateId();
        Position = Vector3.zero;
        Rotation = 0f;
    }
    
    // 多参数构造函数
    public GameEntity(string name, Vector3 position, float rotation = 0f)
    {
        Name = name;
        Id = GenerateId();
        Position = position;
        Rotation = rotation;
    }
    
    // 私有构造函数 (用于单例等模式)
    private GameEntity(int id)
    {
        Id = id;
        Name = $"Entity_{id}";
    }
    
    // 静态工厂方法
    public static GameEntity CreatePlayer(string name)
    {
        return new GameEntity(name) { Id = GenerateId() };
    }
    
    public static GameEntity CreateEnemy(string name, Vector3 spawnPosition)
    {
        return new GameEntity(name, spawnPosition) { Id = GenerateId() };
    }
    
    private static int GenerateId()
    {
        return new System.Random().Next(1000, 9999);
    }
}

// 构造函数调用示例
GameEntity entity1 = new GameEntity();                           // 无参构造
GameEntity entity2 = new GameEntity("Player");                   // 有参构造
GameEntity entity3 = new GameEntity("Enemy", new Vector3(10, 0, 0)); // 多参数构造
GameEntity entity4 = GameEntity.CreatePlayer("Hero");            // 工厂方法

构造函数链 (Constructor Chaining)

public class Weapon
{
    public string Name { get; set; }
    public int Damage { get; set; }
    public float AttackSpeed { get; set; }
    public int Durability { get; set; }
    public string Type { get; set; }
    
    // 基础构造函数
    public Weapon(string name, int damage, float attackSpeed)
    {
        Name = name;
        Damage = damage;
        AttackSpeed = attackSpeed;
        Durability = 100;  // 默认耐久度
        Type = "Weapon";   // 默认类型
    }
    
    // 使用this调用其他构造函数
    public Weapon(string name, int damage) : this(name, damage, 1.0f)
    {
        // 只需设置特定值
    }
    
    // 更复杂的构造函数链
    public Weapon(string name) : this(name, 10)
    {
        // 从最基础的构造函数链式调用
    }
    
    // 带初始化的构造函数
    public Weapon(string name, int damage, float attackSpeed, int durability) 
        : this(name, damage, attackSpeed)
    {
        Durability = durability;
    }
}

// 使用示例
Weapon sword1 = new Weapon("Iron Sword", 25, 1.2f);     // 完整参数
Weapon sword2 = new Weapon("Iron Sword", 25);           // 使用默认攻击速度
Weapon sword3 = new Weapon("Iron Sword");               // 使用默认伤害和速度
Weapon sword4 = new Weapon("Iron Sword", 25, 1.2f, 80); // 带耐久度

析构函数和IDisposable

using System;

public class GameResource : IDisposable
{
    private IntPtr nativeResource;  // 假设这是非托管资源
    private int[] managedResource;  // 托管资源
    private bool disposed = false;
    
    public GameResource()
    {
        // 分配资源
        managedResource = new int[1000];
        // nativeResource = AllocateNativeResource();
    }
    
    // 实现IDisposable接口 (推荐方式)
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);  // 防止析构函数被调用
    }
    
    // 受保护的虚拟方法,允许派生类重写
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // 释放托管资源
                if (managedResource != null)
                {
                    Array.Clear(managedResource, 0, managedResource.Length);
                    managedResource = null;
                }
            }
            
            // 释放非托管资源
            // if (nativeResource != IntPtr.Zero)
            // {
            //     FreeNativeResource(nativeResource);
            //     nativeResource = IntPtr.Zero;
            // }
            
            disposed = true;
        }
    }
    
    // 析构函数 (不推荐,仅作为安全网)
    ~GameResource()
    {
        Dispose(false);
    }
    
    // 确保资源被释放
    public void EnsureResourcesReleased()
    {
        if (!disposed)
        {
            Dispose();
        }
    }
}

// 使用using语句自动释放资源
public class ResourceManager
{
    public void UseResource()
    {
        using (GameResource resource = new GameResource())
        {
            // 使用资源
            // 离开using块时自动调用Dispose()
        }
        // 资源已被释放
    }
}

继承机制

基础继承

// 基类
public class Character
{
    public string Name { get; set; }
    public int Level { get; set; }
    public int Health { get; set; }
    public int MaxHealth { get; set; }
    
    public Character(string name, int level = 1)
    {
        Name = name;
        Level = level;
        MaxHealth = level * 100;
        Health = MaxHealth;
    }
    
    // 虚方法 (可以被重写)
    public virtual void TakeDamage(int damage)
    {
        Health = Math.Max(0, Health - damage);
        Console.WriteLine($"{Name} took {damage} damage. Health: {Health}");
    }
    
    // 普通方法 (不能被重写)
    public void LevelUp()
    {
        Level++;
        MaxHealth += 100;
        Health = MaxHealth;
        Console.WriteLine($"{Name} leveled up to {Level}!");
    }
    
    // 虚方法 - 攻击
    public virtual void Attack(Character target, int baseDamage)
    {
        int damage = baseDamage + Level * 5;
        target.TakeDamage(damage);
    }
}

// 派生类
public class Warrior : Character
{
    public int Strength { get; set; }
    public int Armor { get; set; }
    
    public Warrior(string name, int level = 1) : base(name, level)
    {
        Strength = level * 10;
        Armor = level * 5;
    }
    
    // 重写虚方法
    public override void TakeDamage(int damage)
    {
        int actualDamage = Math.Max(0, damage - Armor);
        base.TakeDamage(actualDamage);  // 调用基类方法
    }
    
    // 重写攻击方法
    public override void Attack(Character target, int baseDamage)
    {
        int damage = baseDamage + Strength + Level * 5;
        Console.WriteLine($"{Name} swings their sword!");
        target.TakeDamage(damage);
    }
    
    // 新方法
    public void Bash(Character target)
    {
        int damage = Strength * 2;
        target.TakeDamage(damage);
        Console.WriteLine($"{Name} bashed {target.Name} for {damage} damage!");
    }
}

// 另一个派生类
public class Mage : Character
{
    public int Intelligence { get; set; }
    public int Mana { get; set; }
    public int MaxMana { get; set; }
    
    public Mage(string name, int level = 1) : base(name, level)
    {
        Intelligence = level * 8;
        MaxMana = level * 50;
        Mana = MaxMana;
    }
    
    public override void Attack(Character target, int baseDamage)
    {
        if (Mana >= 10)
        {
            int damage = baseDamage + Intelligence * 2;
            Mana -= 10;
            Console.WriteLine($"{Name} casts a fireball!");
            target.TakeDamage(damage);
        }
        else
        {
            Console.WriteLine($"{Name} is out of mana!");
        }
    }
    
    public void Heal(Character target)
    {
        if (Mana >= 15)
        {
            int healAmount = Intelligence * 3;
            target.Health = Math.Min(target.MaxHealth, target.Health + healAmount);
            Mana -= 15;
            Console.WriteLine($"{Name} healed {target.Name} for {healAmount}!");
        }
    }
}

继承与C++的对比

特性 C++ C# 说明
继承语法 class Warrior : public Character class Warrior : Character C#更简洁
虚函数 virtual void func() virtual void Func() 相似,但C#需要override
重写 void func() override override void Func() C#需要明确override关键字
访问基类 Base::func() base.Func() 语法不同
多继承 支持 不支持 C#只支持单继承

抽象继承示例

// 抽象基类
public abstract class GameEntity
{
    public string Name { get; set; }
    public Vector3 Position { get; set; }
    public bool IsActive { get; set; } = true;
    
    protected GameEntity(string name)
    {
        Name = name;
    }
    
    // 抽象方法 - 必须在派生类中实现
    public abstract void Update(float deltaTime);
    
    // 虚方法 - 可以在派生类中重写
    public virtual void OnEnable()
    {
        Console.WriteLine($"{Name} enabled");
    }
    
    public virtual void OnDisable()
    {
        Console.WriteLine($"{Name} disabled");
    }
    
    // 具体方法 - 所有派生类继承
    public void MoveTo(Vector3 newPosition)
    {
        Position = newPosition;
    }
    
    // 抽象属性
    public abstract float Speed { get; }
}

// 实现抽象类
public class Enemy : GameEntity
{
    public int Damage { get; set; }
    public float AttackRange { get; set; }
    
    public Enemy(string name) : base(name)
    {
        AttackRange = 2.0f;
    }
    
    public override void Update(float deltaTime)
    {
        // AI更新逻辑
        if (IsActive)
        {
            // 寻找玩家
            // 移动
            // 攻击判断
            Console.WriteLine($"{Name} is updating...");
        }
    }
    
    public override float Speed => 3.0f;  // 实现抽象属性
}

// 另一个实现
public class NPC : GameEntity
{
    public string Dialogue { get; set; }
    public bool IsFriendly { get; set; }
    
    public NPC(string name) : base(name)
    {
        IsFriendly = true;
    }
    
    public override void Update(float deltaTime)
    {
        // NPC行为逻辑
        Console.WriteLine($"{Name} is minding their own business...");
    }
    
    public override float Speed => 1.5f;
    
    public void Talk()
    {
        Console.WriteLine(Dialogue);
    }
}

多态性

多态基础

public class PolymorphismDemo
{
    public static void DemonstratePolymorphism()
    {
        // 创建不同类型的对象
        Character warrior = new Warrior("Conan", 10);
        Character mage = new Mage("Gandalf", 8);
        Character archer = new Archer("Legolas", 7);  // 假设存在Archer类
        
        // 多态数组 - 基类引用指向派生类对象
        Character[] characters = { warrior, mage, archer };
        
        // 多态调用 - 运行时决定调用哪个方法
        foreach (Character character in characters)
        {
            Console.WriteLine($"\n{character.Name} is taking action:");
            character.Attack(warrior, 10);  // 调用各自重写的Attack方法
        }
        
        // 类型检查和转换
        foreach (Character character in characters)
        {
            // as转换 - 失败返回null
            Warrior warriorRef = character as Warrior;
            if (warriorRef != null)
            {
                warriorRef.Bash(mage);  // 只有Warrior有Bash方法
            }
            
            // is检查
            if (character is Mage mageRef)
            {
                mageRef.Heal(character);  // C# 7.0+ 模式匹配
            }
            
            // 传统类型检查
            if (character.GetType() == typeof(Archer))
            {
                Console.WriteLine($"{character.Name} is an Archer");
            }
        }
    }
}

虚方法和重写

public abstract class GameObject
{
    public string Tag { get; set; }
    public bool IsActive { get; set; } = true;
    
    public GameObject(string tag)
    {
        Tag = tag;
    }
    
    // 虚方法 - 可以被重写
    public virtual void Start()
    {
        Console.WriteLine($"{Tag} started");
    }
    
    // 抽象方法 - 必须被重写
    public abstract void Update(float deltaTime);
    
    // 虚方法 - 有默认实现
    public virtual void OnTriggerEnter(GameObject other)
    {
        Console.WriteLine($"{Tag} triggered with {other.Tag}");
    }
    
    // 密封方法 - 不能被进一步重写
    public virtual void OnCollision(GameObject other)
    {
        Console.WriteLine($"{Tag} collided with {other.Tag}");
    }
    
    public sealed override string ToString()
    {
        return $"GameObject: {Tag}";
    }
}

public class PlayerObject : GameObject
{
    public int Score { get; set; }
    public float Speed { get; set; } = 5.0f;
    
    public PlayerObject() : base("Player")
    {
    }
    
    public override void Start()
    {
        base.Start();  // 调用基类方法
        Console.WriteLine("Player controls initialized");
    }
    
    public override void Update(float deltaTime)
    {
        // 处理玩家输入
        // 移动逻辑
        Console.WriteLine($"Player updated with delta: {deltaTime}");
    }
    
    // 重写触发方法
    public override void OnTriggerEnter(GameObject other)
    {
        if (other.Tag == "Coin")
        {
            Score += 10;
            Console.WriteLine($"Player collected coin! Score: {Score}");
        }
        else
        {
            base.OnTriggerEnter(other);  // 调用基类实现
        }
    }
    
    // 重写碰撞方法
    public override void OnCollision(GameObject other)
    {
        base.OnCollision(other);
        // 玩家特定的碰撞处理
        if (other.Tag == "Enemy")
        {
            Console.WriteLine("Player took damage from enemy!");
        }
    }
}

public class EnemyObject : GameObject
{
    public int Health { get; set; } = 100;
    public float AttackPower { get; set; } = 20;
    
    public EnemyObject() : base("Enemy")
    {
    }
    
    public override void Update(float deltaTime)
    {
        // AI逻辑
        Console.WriteLine($"Enemy AI updated with delta: {deltaTime}");
    }
    
    public override void OnTriggerEnter(GameObject other)
    {
        if (other.Tag == "Player")
        {
            Console.WriteLine("Enemy detected player!");
            AttackPlayer(other as PlayerObject);
        }
        else
        {
            base.OnTriggerEnter(other);
        }
    }
    
    private void AttackPlayer(PlayerObject player)
    {
        if (player != null)
        {
            Console.WriteLine($"Enemy attacks player for {AttackPower} damage!");
        }
    }
}

接口多态

// 定义接口
public interface IInteractable
{
    void OnInteract(Player player);
    bool CanInteract(Player player);
}

public interface IMovable
{
    void Move(Vector3 direction);
    float Speed { get; }
}

public interface IDamageable
{
    int Health { get; set; }
    void TakeDamage(int damage);
    bool IsAlive { get; }
}

// 类实现多个接口
public class InteractiveObject : IInteractable, IMovable, IDamageable
{
    public string Name { get; set; }
    public int Health { get; set; } = 100;
    public float Speed { get; set; } = 3.0f;
    
    public InteractiveObject(string name)
    {
        Name = name;
    }
    
    // 实现IInteractable
    public void OnInteract(Player player)
    {
        Console.WriteLine($"{player.Name} interacts with {Name}");
    }
    
    public bool CanInteract(Player player)
    {
        return Health > 0 && Vector3.Distance(player.Position, this.Position) < 3.0f;
    }
    
    // 实现IMovable
    public void Move(Vector3 direction)
    {
        // 移动逻辑
        this.Position += direction * Speed * Time.deltaTime;
    }
    
    // 实现IDamageable
    public void TakeDamage(int damage)
    {
        Health -= damage;
        if (Health <= 0)
        {
            Health = 0;
            Console.WriteLine($"{Name} has been destroyed!");
        }
    }
    
    public bool IsAlive => Health > 0;
    
    // 类特有的属性
    public Vector3 Position { get; set; }
}

// 多态使用示例
public class InterfacePolymorphism
{
    public static void Demonstrate()
    {
        InteractiveObject obj = new InteractiveObject("Chest");
        Player player = new Player("Hero");
        
        // 通过不同接口引用同一对象
        IInteractable interactable = obj;
        IMovable movable = obj;
        IDamageable damageable = obj;
        
        // 多态调用
        if (interactable.CanInteract(player))
        {
            interactable.OnInteract(player);
        }
        
        movable.Move(new Vector3(1, 0, 0));
        damageable.TakeDamage(25);
        
        Console.WriteLine($"Health after damage: {damageable.Health}");
    }
}

抽象类和接口

抽象类详解

// 抽象类 - 不能直接实例化
public abstract class GameCharacter
{
    // 具体字段
    protected string name;
    protected int level;
    protected int health;
    
    // 属性
    public string Name => name;
    public int Level 
    { 
        get => level;
        protected set => level = Math.Max(1, value);
    }
    public int Health 
    { 
        get => health;
        set => health = Math.Clamp(value, 0, MaxHealth);
    }
    
    // 抽象属性 - 必须在派生类中实现
    public abstract int MaxHealth { get; }
    public abstract float MoveSpeed { get; }
    
    // 构造函数
    protected GameCharacter(string name, int level = 1)
    {
        this.name = name;
        this.level = level;
        this.health = MaxHealth;  // 使用抽象属性
    }
    
    // 具体方法 - 所有派生类继承
    public void LevelUp()
    {
        Level++;
        Health = MaxHealth;  // 满血升级
        Console.WriteLine($"{Name} leveled up to {Level}!");
    }
    
    // 虚方法 - 可以在派生类中重写
    public virtual void TakeDamage(int damage)
    {
        Health -= damage;
        Console.WriteLine($"{Name} took {damage} damage. Health: {Health}");
    }
    
    // 抽象方法 - 必须在派生类中实现
    public abstract void Attack(GameCharacter target);
    
    // 抽象方法 - 移动
    public abstract void Move(Vector3 direction);
    
    // 具体方法 - 检查是否存活
    public bool IsAlive() => Health > 0;
    
    // 虚方法 - 特殊技能
    public virtual void UseSpecialAbility()
    {
        Console.WriteLine($"{Name} used a basic ability");
    }
}

// 具体实现类
public class Knight : GameCharacter
{
    public int Armor { get; set; }
    public int ShieldPower { get; set; }
    
    public Knight(string name, int level = 1) : base(name, level)
    {
        Armor = level * 5;
        ShieldPower = level * 3;
    }
    
    public override int MaxHealth => Level * 120;  // 实现抽象属性
    public override float MoveSpeed => 3.0f;
    
    public override void Attack(GameCharacter target)
    {
        int damage = Level * 15 + Armor / 2;
        Console.WriteLine($"{Name} attacks with sword for {damage} damage!");
        target.TakeDamage(damage);
    }
    
    public override void Move(Vector3 direction)
    {
        // 骑士移动逻辑
        Console.WriteLine($"{Name} moves slowly with armor");
    }
    
    public override void TakeDamage(int damage)
    {
        int reducedDamage = Math.Max(0, damage - Armor / 3);
        base.TakeDamage(reducedDamage);
    }
    
    public override void UseSpecialAbility()
    {
        Console.WriteLine($"{Name} raises shield, reducing damage by {ShieldPower}!");
    }
}

public class Archer : GameCharacter
{
    public int Agility { get; set; }
    public float AttackRange { get; set; } = 10f;
    
    public Archer(string name, int level = 1) : base(name, level)
    {
        Agility = level * 8;
    }
    
    public override int MaxHealth => Level * 80;
    public override float MoveSpeed => 5.0f;
    
    public override void Attack(GameCharacter target)
    {
        int damage = Level * 12 + Agility / 2;
        Console.WriteLine($"{Name} shoots arrow at {target.Name} for {damage} damage!");
        
        // 检查距离
        float distance = Vector3.Distance(this.Position, target.Position);
        if (distance > AttackRange)
        {
            Console.WriteLine("Target is too far!");
            return;
        }
        
        target.TakeDamage(damage);
    }
    
    public override void Move(Vector3 direction)
    {
        Console.WriteLine($"{Name} moves quickly with bow ready");
    }
    
    public override void UseSpecialAbility()
    {
        Console.WriteLine($"{Name} performs a critical shot!");
    }
    
    public Vector3 Position { get; set; } = Vector3.zero;
}

接口详解

// 单一职责接口
public interface IAttackable
{
    void Attack(IDamageable target, int baseDamage);
    int AttackPower { get; }
}

public interface IDamageable
{
    int Health { get; set; }
    int MaxHealth { get; }
    void TakeDamage(int damage);
    bool IsAlive { get; }
}

public interface IMovable
{
    Vector3 Position { get; set; }
    float Speed { get; }
    void Move(Vector3 direction);
    void Rotate(float angle);
}

public interface ICollectable
{
    string ItemName { get; }
    int Value { get; }
    void OnCollected(GameObject collector);
}

// 接口继承
public interface IGameEntity : IMovable, IDamageable
{
    string Tag { get; set; }
    bool IsActive { get; set; }
    void Initialize();
    void Update(float deltaTime);
}

// 接口实现示例
public class GameItem : ICollectable
{
    public string ItemName { get; private set; }
    public int Value { get; private set; }
    public string ItemType { get; private set; }
    
    public GameItem(string name, int value, string type)
    {
        ItemName = name;
        Value = value;
        ItemType = type;
    }
    
    public void OnCollected(GameObject collector)
    {
        Console.WriteLine($"{collector.Name} collected {ItemName} worth {Value} points!");
        
        // 根据物品类型执行不同逻辑
        switch (ItemType)
        {
            case "HealthPotion":
                // 恢复生命
                break;
            case "Coin":
                // 增加金币
                break;
            case "Key":
                // 解锁功能
                break;
        }
    }
}

// 复杂类实现多个接口
public class PlayerCharacter : IGameEntity, IAttackable
{
    public string Tag { get; set; } = "Player";
    public bool IsActive { get; set; } = true;
    public Vector3 Position { get; set; } = Vector3.zero;
    public float Speed { get; } = 5.0f;
    public int Health { get; set; } = 100;
    public int MaxHealth { get; } = 100;
    public int AttackPower { get; set; } = 25;
    public string Name { get; set; }
    
    public PlayerCharacter(string name)
    {
        Name = name;
    }
    
    // IGameEntity 实现
    public void Initialize()
    {
        Console.WriteLine($"Player {Name} initialized at {Position}");
    }
    
    public void Update(float deltaTime)
    {
        // 玩家更新逻辑
        HandleInput();
    }
    
    // IMovable 实现
    public void Move(Vector3 direction)
    {
        Position += direction * Speed * Time.deltaTime;
    }
    
    public void Rotate(float angle)
    {
        // 旋转逻辑
    }
    
    // IDamageable 实现
    public void TakeDamage(int damage)
    {
        Health = Math.Max(0, Health - damage);
        Console.WriteLine($"Player took {damage} damage. Health: {Health}");
    }
    
    public bool IsAlive => Health > 0;
    
    // IAttackable 实现
    public void Attack(IDamageable target, int baseDamage)
    {
        Console.WriteLine($"{Name} attacks target!");
        target.TakeDamage(baseDamage + AttackPower);
    }
    
    // 私有方法
    private void HandleInput()
    {
        // 处理玩家输入
    }
}

接口 vs 抽象类对比

// 接口 - 定义契约
public interface IWeapon
{
    int Damage { get; }
    float AttackSpeed { get; }
    void Use(ICharacter target);
}

// 抽象类 - 提供部分实现
public abstract class WeaponBase
{
    public string Name { get; protected set; }
    public int Damage { get; protected set; }
    public float AttackSpeed { get; protected set; }
    public int Durability { get; protected set; }
    
    protected WeaponBase(string name, int damage, float speed)
    {
        Name = name;
        Damage = damage;
        AttackSpeed = speed;
        Durability = 100;
    }
    
    // 具体方法 - 所有武器共享
    public void ReduceDurability(int amount)
    {
        Durability = Math.Max(0, Durability - amount);
        if (Durability <= 0)
        {
            Console.WriteLine($"{Name} has broken!");
        }
    }
    
    // 抽象方法 - 每种武器实现不同
    public abstract void Use(ICharacter target);
    
    // 虚方法 - 可以重写
    public virtual bool IsUsable()
    {
        return Durability > 0;
    }
}

// 具体武器实现
public class Sword : WeaponBase, IWeapon
{
    public int Sharpness { get; set; }
    
    public Sword(string name, int damage) : base(name, damage, 1.2f)
    {
        Sharpness = 10;
    }
    
    public void IWeapon.Use(ICharacter target)  // 显式接口实现
    {
        Use(target);
    }
    
    public override void Use(ICharacter target)
    {
        if (IsUsable())
        {
            int actualDamage = Damage + Sharpness;
            target.TakeDamage(actualDamage);
            ReduceDurability(5);
            Console.WriteLine($"Slash with {Name} for {actualDamage} damage!");
        }
    }
}

public class Bow : WeaponBase
{
    public float Range { get; set; } = 20f;
    
    public Bow(string name, int damage) : base(name, damage, 0.8f)
    {
        Range = 20f;
    }
    
    public override void Use(ICharacter target)
    {
        if (IsUsable())
        {
            // 检查距离
            float distance = Vector3.Distance(this.Position, target.Position);
            if (distance <= Range)
            {
                target.TakeDamage(Damage);
                ReduceDurability(2);
                Console.WriteLine($"Shoot arrow with {Name} for {Damage} damage!");
            }
            else
            {
                Console.WriteLine("Target is too far!");
            }
        }
    }
    
    public Vector3 Position { get; set; }
}

访问修饰符

访问修饰符详解

public class AccessModifiersDemo
{
    // public: 任何地方都可以访问
    public int PublicField = 1;
    public void PublicMethod() { }
    
    // private: 只能在本类内部访问 (默认)
    private int PrivateField = 2;
    private void PrivateMethod() { }
    
    // protected: 本类和派生类可以访问
    protected int ProtectedField = 3;
    protected void ProtectedMethod() { }
    
    // internal: 同一程序集内可以访问
    internal int InternalField = 4;
    internal void InternalMethod() { }
    
    // protected internal: 同一程序集内或派生类可以访问
    protected internal int ProtectedInternalField = 5;
    
    // private protected: 本类或同一程序集内的派生类可以访问 (C# 7.2+)
    private protected int PrivateProtectedField = 6;
    
    public void AccessDemo()
    {
        // 在本类内部可以访问所有成员 (除了其他实例的private)
        Console.WriteLine($"Public: {PublicField}");
        Console.WriteLine($"Private: {PrivateField}");
        Console.WriteLine($"Protected: {ProtectedField}");
        Console.WriteLine($"Internal: {InternalField}");
    }
}

// 派生类可以访问protected成员
public class DerivedClass : AccessModifiersDemo
{
    public void DerivedAccessDemo()
    {
        // 可以访问protected成员
        Console.WriteLine($"Protected: {ProtectedField}");
        Console.WriteLine($"Protected Internal: {ProtectedInternalField}");
        
        // 不能访问private成员
        // Console.WriteLine(PrivateField); // 编译错误
    }
}

// 不同程序集中的类
public class ExternalClass
{
    public void ExternalAccessDemo()
    {
        AccessModifiersDemo demo = new AccessModifiersDemo();
        
        // 只能访问public成员
        Console.WriteLine($"Public: {demo.PublicField}");
        
        // 不能访问非public成员
        // Console.WriteLine(demo.PrivateField); // 编译错误
        // Console.WriteLine(demo.ProtectedField); // 编译错误
    }
}

封装示例

public class BankAccount
{
    // 私有字段 - 存储实际数据
    private decimal balance;
    private string accountNumber;
    private DateTime createdDate;
    
    // 只读属性 - 外部可以读取但不能直接修改
    public string AccountNumber => accountNumber;
    public DateTime CreatedDate => createdDate;
    public DateTime LastModified { get; private set; }
    
    // 公共属性 - 带验证的访问
    public decimal Balance 
    { 
        get => balance;
        private set  // 只有本类可以修改
        {
            balance = value;
            LastModified = DateTime.Now;
        }
    }
    
    // 可读写属性
    public string OwnerName { get; set; }
    public string BankName { get; set; }
    
    public BankAccount(string accountNumber, string ownerName, decimal initialBalance = 0)
    {
        this.accountNumber = accountNumber;
        this.OwnerName = ownerName;
        this.balance = Math.Max(0, initialBalance);
        this.createdDate = DateTime.Now;
        this.LastModified = DateTime.Now;
    }
    
    // 公共方法 - 控制访问
    public bool Deposit(decimal amount)
    {
        if (amount > 0)
        {
            Balance += amount;
            LogTransaction("Deposit", amount);
            return true;
        }
        return false;
    }
    
    public bool Withdraw(decimal amount)
    {
        if (amount > 0 && balance >= amount)
        {
            Balance -= amount;
            LogTransaction("Withdrawal", -amount);
            return true;
        }
        return false;
    }
    
    // 内部方法 - 只有本类使用
    private void LogTransaction(string type, decimal amount)
    {
        Console.WriteLine($"[{DateTime.Now}] {type}: {amount:C} | Balance: {Balance:C}");
    }
    
    // 受保护方法 - 派生类可以访问
    protected void InternalTransfer(decimal amount, BankAccount target)
    {
        if (this.Withdraw(amount))
        {
            target.Deposit(amount);
        }
    }
}

// 使用示例
public class BankingDemo
{
    public static void Demonstrate()
    {
        BankAccount account = new BankAccount("12345", "John Doe", 1000);
        
        Console.WriteLine($"Account: {account.AccountNumber}");
        Console.WriteLine($"Owner: {account.OwnerName}");
        Console.WriteLine($"Balance: {account.Balance:C}");
        
        account.Deposit(500);
        account.Withdraw(200);
        
        Console.WriteLine($"Final Balance: {account.Balance:C}");
        
        // 以下操作是不允许的:
        // account.Balance = 9999;  // 编译错误 - Balance的setter是private
        // account.accountNumber = "67890";  // 编译错误 - accountNumber是private字段
    }
}

C#与C++ OOP差异总结

1. 继承机制

C++:

class Character {
public:
    virtual void Attack() = 0;  // 纯虚函数
    virtual ~Character() {}      // 虚析构函数
};

class Warrior : public Character {
public:
    void Attack() override { }  // 重写
};

C#:

public abstract class Character {
    public abstract void Attack();  // 抽象方法
}

public class Warrior : Character {
    public override void Attack() { }  // 重写,必须使用override
}

2. 访问控制

C++:

class GameEntity {
private:
    int health;
protected:
    int level;
public:
    int score;
};

C#:

public class GameEntity {
    private int health;     // 或使用默认访问级别
    protected int level;
    public int Score { get; set; }  // 属性而非字段
}

3. 多重继承

C++: 支持多重继承

class Flying : public Character, public IMovable { ... };

C#: 不支持多重继承,但支持多接口实现

public class Flying : Character, IMovable, IFlyable { ... };

4. 析构和资源管理

C++:

class GameResource {
public:
    ~GameResource() {  // 析构函数
        // 清理资源
    }
};

C#:

public class GameResource : IDisposable {
    ~GameResource() {  // 析构函数(终结器)
        // 仅作为安全网
    }
    
    public void Dispose() {  // 实现IDisposable
        // 清理资源
    }
}

5. 属性系统

C++: 需要手动实现getter/setter

class Player {
private:
    int health;
public:
    int GetHealth() const { return health; }
    void SetHealth(int h) { health = h; }
};

C#: 内置属性系统

public class Player {
    public int Health { get; set; }  // 自动实现
    public int MaxHealth { get; private set; }  // 私有setter
}

实践练习

练习1: 游戏单位层次结构

// 游戏单位基类
public abstract class Unit
{
    public string Name { get; set; }
    public Vector3 Position { get; set; }
    public float Health { get; set; }
    public float MaxHealth { get; protected set; }
    public float Speed { get; set; }
    public int Level { get; set; }
    public bool IsAlive => Health > 0;
    
    protected Unit(string name, float maxHealth, float speed, int level = 1)
    {
        Name = name;
        MaxHealth = maxHealth;
        Health = maxHealth;
        Speed = speed;
        Level = level;
    }
    
    public abstract void Attack(Unit target);
    public virtual void TakeDamage(float damage)
    {
        Health = Math.Max(0, Health - damage);
        if (!IsAlive)
        {
            OnDeath();
        }
    }
    
    protected virtual void OnDeath()
    {
        Console.WriteLine($"{Name} has been defeated!");
    }
    
    public virtual void Move(Vector3 direction)
    {
        Position += direction * Speed * Time.deltaTime;
    }
}

// 具体单位类型
public class Soldier : Unit
{
    public float AttackPower { get; set; }
    public float AttackRange { get; set; }
    
    public Soldier(string name, int level = 1) : base(name, 100, 3.0f, level)
    {
        AttackPower = level * 15;
        AttackRange = 2.0f;
    }
    
    public override void Attack(Unit target)
    {
        if (Vector3.Distance(Position, target.Position) <= AttackRange)
        {
            target.TakeDamage(AttackPower);
            Console.WriteLine($"{Name} attacks {target.Name} for {AttackPower} damage!");
        }
        else
        {
            Console.WriteLine($"{Name} is too far from {target.Name}!");
        }
    }
}

public class Archer : Unit
{
    public float AttackPower { get; set; }
    public float AttackRange { get; set; } = 10.0f;
    public int ArrowCount { get; set; } = 20;
    
    public Archer(string name, int level = 1) : base(name, 70, 4.0f, level)
    {
        AttackPower = level * 12;
    }
    
    public override void Attack(Unit target)
    {
        if (ArrowCount <= 0)
        {
            Console.WriteLine($"{Name} is out of arrows!");
            return;
        }
        
        if (Vector3.Distance(Position, target.Position) <= AttackRange)
        {
            target.TakeDamage(AttackPower);
            ArrowCount--;
            Console.WriteLine($"{Name} shoots {target.Name} for {AttackPower} damage! Arrows left: {ArrowCount}");
        }
        else
        {
            Console.WriteLine($"{Name} is too far from {target.Name}!");
        }
    }
    
    public void Reload()
    {
        ArrowCount = 20;
        Console.WriteLine($"{Name} reloaded arrows!");
    }
}

// 游戏管理器
public class GameManager
{
    private List<Unit> units = new List<Unit>();
    
    public void AddUnit(Unit unit)
    {
        units.Add(unit);
    }
    
    public void Update(float deltaTime)
    {
        // 多态更新
        foreach (Unit unit in units)
        {
            if (unit.IsAlive)
            {
                unit.Move(new Vector3(1, 0, 0));  // 简单移动AI
            }
        }
    }
    
    public void Battle(Unit attacker, Unit defender)
    {
        if (attacker.IsAlive && defender.IsAlive)
        {
            attacker.Attack(defender);
            
            // 如果弓箭手,可能需要特殊处理
            if (attacker is Archer archer && archer.ArrowCount <= 0)
            {
                Console.WriteLine($"{archer.Name} needs to reload!");
            }
        }
    }
}

练习2: 装备系统

// 装备接口
public interface IEquipment
{
    string Name { get; }
    int LevelRequirement { get; }
    EquipmentType Type { get; }
    void Equip(Character character);
    void UnEquip(Character character);
    bool CanEquip(Character character);
}

public enum EquipmentType
{
    Weapon,
    Armor,
    Accessory
}

// 抽象装备类
public abstract class Equipment : IEquipment
{
    public string Name { get; protected set; }
    public int LevelRequirement { get; protected set; }
    public EquipmentType Type { get; protected set; }
    public int Value { get; protected set; }
    public bool IsEquipped { get; private set; }
    
    protected Equipment(string name, int levelReq, EquipmentType type, int value)
    {
        Name = name;
        LevelRequirement = levelReq;
        Type = type;
        Value = value;
    }
    
    public virtual bool CanEquip(Character character)
    {
        return character.Level >= LevelRequirement && !IsEquipped;
    }
    
    public abstract void Equip(Character character);
    public abstract void UnEquip(Character character);
}

// 武器装备
public class Weapon : Equipment
{
    public int AttackPower { get; private set; }
    public float AttackSpeed { get; private set; }
    
    public Weapon(string name, int levelReq, int attackPower, float attackSpeed) 
        : base(name, levelReq, EquipmentType.Weapon, attackPower * 10)
    {
        AttackPower = attackPower;
        AttackSpeed = attackSpeed;
    }
    
    public override void Equip(Character character)
    {
        if (CanEquip(character))
        {
            character.AddAttackPower(AttackPower);
            character.AddAttackSpeed(AttackSpeed);
            IsEquipped = true;
            Console.WriteLine($"{character.Name} equipped {Name}");
        }
    }
    
    public override void UnEquip(Character character)
    {
        character.SubtractAttackPower(AttackPower);
        character.SubtractAttackSpeed(AttackSpeed);
        IsEquipped = false;
        Console.WriteLine($"{character.Name} unequipped {Name}");
    }
}

// 防具装备
public class Armor : Equipment
{
    public int Defense { get; private set; }
    public int MaxHealthBonus { get; private set; }
    
    public Armor(string name, int levelReq, int defense, int healthBonus) 
        : base(name, levelReq, EquipmentType.Armor, defense * 8)
    {
        Defense = defense;
        MaxHealthBonus = healthBonus;
    }
    
    public override void Equip(Character character)
    {
        if (CanEquip(character))
        {
            character.AddDefense(Defense);
            character.AddMaxHealth(MaxHealthBonus);
            IsEquipped = true;
            Console.WriteLine($"{character.Name} equipped {Name}");
        }
    }
    
    public override void UnEquip(Character character)
    {
        character.SubtractDefense(Defense);
        character.SubtractMaxHealth(MaxHealthBonus);
        IsEquipped = false;
        Console.WriteLine($"{character.Name} unequipped {Name}");
    }
}

// 角色类
public class Character
{
    public string Name { get; set; }
    public int Level { get; set; }
    public float Health { get; set; }
    public float MaxHealth { get; private set; }
    public int AttackPower { get; private set; }
    public float AttackSpeed { get; private set; }
    public int Defense { get; private set; }
    
    private List<IEquipment> equipment = new List<IEquipment>();
    
    public Character(string name, int level = 1)
    {
        Name = name;
        Level = level;
        MaxHealth = level * 100;
        Health = MaxHealth;
        AttackPower = level * 10;
        AttackSpeed = 1.0f;
        Defense = level * 2;
    }
    
    // 装备管理
    public bool EquipItem(IEquipment item)
    {
        if (item.CanEquip(this))
        {
            if (HasEquipmentOfType(item.Type))
            {
                UnequipItemOfType(item.Type);
            }
            
            item.Equip(this);
            equipment.Add(item);
            return true;
        }
        return false;
    }
    
    public void UnequipItem(IEquipment item)
    {
        if (equipment.Contains(item))
        {
            item.UnEquip(this);
            equipment.Remove(item);
        }
    }
    
    private bool HasEquipmentOfType(EquipmentType type)
    {
        return equipment.Any(e => e.Type == type);
    }
    
    private void UnequipItemOfType(EquipmentType type)
    {
        IEquipment existing = equipment.FirstOrDefault(e => e.Type == type);
        if (existing != null)
        {
            UnequipItem(existing);
        }
    }
    
    // 属性修改方法
    public void AddAttackPower(int amount) => AttackPower += amount;
    public void AddAttackSpeed(float amount) => AttackSpeed += amount;
    public void AddDefense(int amount) => Defense += amount;
    public void AddMaxHealth(int amount)
    {
        MaxHealth += amount;
        Health += amount;  // 装备时增加当前生命值
    }
    
    public void SubtractAttackPower(int amount) => AttackPower = Math.Max(0, AttackPower - amount);
    public void SubtractAttackSpeed(float amount) => AttackSpeed = Math.Max(0.1f, AttackSpeed - amount);
    public void SubtractDefense(int amount) => Defense = Math.Max(0, Defense - amount);
    public void SubtractMaxHealth(int amount)
    {
        MaxHealth = Math.Max(1, MaxHealth - amount);
        Health = Math.Min(Health, MaxHealth);
    }
}

// 使用示例
public class EquipmentDemo
{
    public static void Run()
    {
        Character player = new Character("Hero", 10);
        Weapon sword = new Weapon("Magic Sword", 5, 50, 1.2f);
        Armor chestplate = new Armor("Dragon Chestplate", 8, 30, 150);
        
        Console.WriteLine($"初始攻击力: {player.AttackPower}, 生命值: {player.MaxHealth}");
        
        // 装备武器
        if (player.EquipItem(sword))
        {
            Console.WriteLine($"装备后攻击力: {player.AttackPower}");
        }
        
        // 装备防具
        if (player.EquipItem(chestplate))
        {
            Console.WriteLine($"装备后生命值: {player.MaxHealth}, 防御力: {player.Defense}");
        }
    }
}

常见错误和最佳实践

1. 避免过度继承

// 错误: 过深的继承层次
public class GameObject { }
public class LivingObject : GameObject { }
public class Character : LivingObject { }
public class Player : Character { }
public class Warrior : Player { }  // 继承层次过深

// 正确: 使用组合而非继承
public class Warrior
{
    public CharacterBase Base { get; set; }
    public CombatSystem Combat { get; set; }
    public EquipmentSystem Equipment { get; set; }
}

2. 正确使用虚方法

public class GameEntity
{
    // 正确: 为可能被重写的提供虚方法
    public virtual void Update(float deltaTime)
    {
        // 基础更新逻辑
    }
    
    // 正确: 为必须被重写的提供抽象方法
    public abstract void Initialize();
    
    // 正确: 为不应该被重写的提供密封方法
    public virtual void CriticalSystem()
    {
        // 关键系统逻辑
    }
    
    public sealed override string ToString()
    {
        return $"GameEntity: {this.GetType().Name}";
    }
}

3. 接口设计原则

// 正确: 遵循接口隔离原则
public interface IMovable { void Move(Vector3 direction); }
public interface IAttackable { void Attack(IDamageable target); }
public interface IDamageable { void TakeDamage(int damage); }

// 而不是: 大而全的接口
// public interface IGameCharacter { void Move(); void Attack(); void TakeDamage(); ... }

总结

本章我们深入学习了C#的面向对象编程:

类和对象: 类定义、对象创建、部分类、静态类
属性和字段: 自动属性、完整属性、只读属性、索引器
构造函数: 多种构造函数、构造函数链、资源管理
继承机制: 单继承、基类访问、构造函数链
多态性: 虚方法、重写、接口多态
抽象类和接口: 抽象类设计、接口实现、多重接口
访问修饰符: 各种访问级别、封装实践

C#的面向对象特性比C++更加安全和易用,提供了更好的封装性、更清晰的继承关系和更灵活的多态机制。


下一步

继续学习 04. LINQ和集合框架