C#静态派生类不可用的替代实现方案咨询(含技能、宝可梦类场景)
C# 静态派生类限制的替代实现方案(宝可梦场景)
核心需求梳理
你当前的核心诉求是两点:
- 技能类属性固定,不需要为每个宝可梦实例重复创建技能对象
- 规避C#不允许静态类继承自定义基类的限制
最优实现方案
方案1:技能类用单例模式复用实例(适配你现有派生类结构)
不需要修改现有Move继承结构,只要给每个技能派生类加全局唯一实例、私有化构造函数禁止外部随意创建即可,完全避免重复生成实例的问题:
abstract class Move { // 注意字段要改为public/protected才能被外部/派生类访问 public int Damage { get; } public string Name { get; } public Move(int damage, string name) { Damage = damage; Name = name; } } class Tackle : Move { // 全局唯一实例,所有宝可梦共用这一个对象 public static readonly Tackle Instance = new Tackle(); // 构造函数私有化,禁止外部随意new private Tackle() : base(20, "Tackle") { } } class Ember: Move { public static readonly Ember Instance = new Ember(); private Ember() : base(30, "Ember") { } }
使用时直接引用静态实例即可,不需要新建对象:
// 妙蛙种子的可学技能直接引用全局实例 Move[] possibleMoves = { Tackle.Instance };
方案2:移除技能派生类,统一用静态全局实例存储(更简洁)
如果所有技能没有特殊的自定义逻辑,完全可以删掉所有Move的派生类,用静态字段统一管理所有技能,代码更精简:
public sealed class Move { public int Damage { get; } public string Name { get; } // 构造函数私有化,禁止外部创建实例 private Move(int damage, string name) { Damage = damage; Name = name; } // 所有技能的全局唯一实例都存在此处 public static readonly Move Tackle = new Move(20, "Tackle"); public static readonly Move Ember = new Move(30, "Ember"); public static readonly Move Flamethrower = new Move(90, "喷射火焰"); public static readonly Move Watergun = new Move(40, "水枪"); }
宝可梦类的优化建议
你当前为每个宝可梦写派生类存储静态种族属性的写法可用,但可维护性较差,可以抽离种族静态数据层,避免写大量冗余派生类,后续加新宝可梦只需要加一行配置即可:
// 种族数据层,存储所有宝可梦共通的静态种族属性 public sealed class PokemonSpecies { public string SpeciesName { get; } public int BaseHealth { get; } public Move[] LearnableMoves { get; } private PokemonSpecies(string speciesName, int baseHealth, Move[] learnableMoves) { SpeciesName = speciesName; BaseHealth = baseHealth; LearnableMoves = learnableMoves; } // 所有宝可梦种族的静态实例 public static readonly PokemonSpecies Bulbasaur = new PokemonSpecies("妙蛙种子", 60, new[] { Move.Tackle }); public static readonly PokemonSpecies Charmander = new PokemonSpecies("小火龙", 50, new[] { Move.Tackle, Move.Ember }); } // 宝可梦实例类,不需要再写大量派生类 public class Pokemon { public PokemonSpecies Species { get; } public int CurrentHealth { get; set; } public string NickName { get; set; } public int Level { get; set; } public Move[] EquippedMoves { get; set; } public bool Fainted => CurrentHealth <= 0; public Pokemon(PokemonSpecies species) { Species = species; CurrentHealth = species.BaseHealth; } public void TakeDamage(int damage) { CurrentHealth = Math.Max(0, CurrentHealth - damage); } }
内容的提问来源于stack exchange,提问作者user11718790
相关产品推荐
相关产品推荐

