在具有超类输入的泛型方法中访问的子类属性

本文关键字:访问 子类 属性 泛型方法 超类 输入 | 更新日期: 2023-09-27 18:32:16

我想制作一个库存/装备系统来与我的物品系统接口。我的条目系统是基于共享属性的继承类系统。

我将类型存储在枚举中,并为项目提供一个枚举值。

我的继承结构:

Item {
  Equippable {
    Armor {Chest, Head}
    Weapon {Melee, Ranged}
  }
}

我让每个子类型在其父类中定义一个枚举变量,因此 Chest 会在使用该类型的显式基构造函数调用中定义 armorType 枚举。

例如

public enum armorTypes {Chest, Helmet}
public class Armor : Equippable
{
    armorTypes armorType;
    public Armor(armorTypes at) : base(equippableTypes.Armor) 
    {
        armorType = at;
    }
}
public class Chest : Armor 
{
    int defense = 10;
    public Chest() : base(armorTypes.Chest) {}
}
public class Helmet : Armor 
{
    int defense = 5;
    public Helmet() : base(armorTypes.Helmet) {}
}

在我的库存类中,我有这些项目的空白版本。

Inventory{
  public Chest chestSlot;
  public Helmet helmetSlot;
  public Melee meleeSlot;
  public Ranged rangedSlot;
}

我想根据它们的属性比较两个插槽中的对象。

void Compare(Item item) 
{
  switch((item as Armor).armorType)
  {
      case armorTypes.Chest :
        Console.WriteLine((item as Chest).defense + " or " + chestSlot.defense);
        break;
      case armorTypes.Helmet :
        Console.WriteLine((item as Helmet).defense + " or " + helmetSlot.defense);
        break;
  }
}

但是,当我使用 as 关键字转换它时,不知何故我丢失了我的实例?

另外,由于我需要访问 item.armorType 我无法封装 Armor,可以吗?

在具有超类输入的泛型方法中访问的子类属性

这就是我实现它的方式。首先,让基类定义基本的比较方法:

abstract class Item 
{
    // these methods define base comparison operations;
    // by default, items are not comparable;
    public virtual bool CanCompareWith(Item item)
    {
        return false;
    }
    // since we don't know all possible item properties,
    // this method hasn't implementation
    public abstract void CompareWith(Item item);
}

接下来,我们必须定义一些默认设备。装甲:

abstract class Equippable : Item {}    
abstract class Armor : Equippable
{
    // every armor has a Defence property
    public abstract int Defence { get; }
    // the base comparison logic of two armors
    public override void CompareWith(Item item)
    {
        Console.WriteLine("{0} or {1}", ((Armor)item).Defence, this.Defence);
    }
}
class Chest : Armor
{
    // if you want for chests to be comared with chests only:
    public override bool CanCompareWith(Item item)
    {
        return item is Chest;
    }
    public override int Defence
    {
        get { return 10; }
    }
}
class Helmet : Armor
{
    public override bool CanCompareWith(Item item)
    {
        return item is Helmet;
    }
    public override int Defence
    {
        get { return 5; }
    }
}

武器:

abstract class Weapon : Equippable
{
    // every weapon has Attack property
    public abstract int Attack { get; }
    // the base comparison logc of two weapons
    public override void CompareWith(Item item)
    {
        Console.WriteLine("{0} or {1}", ((Weapon)item).Attack, this.Attack);
    }
}
class Melee : Weapon
{
    public override bool CanCompareWith(Item item)
    {
        return item is Melee;
    }
    public override int Attack
    {
        get { return 20; }
    }
}
class Ranged : Weapon
{
    public override bool CanCompareWith(Item item)
    {
        return item is Ranged;
    }
    public override int Attack
    {
        get { return 25; }
    }
}

请注意,这里没有任何枚举。这是因为类型本身(例如,ChestHelmet等)定义了具体项目所属的位置。枚举在这里只是多余的。

这是库存:

class Inventory
{
    // this is inventory storage;
    // collection allows the storage to be extended later, or be displayed at once
    // (e.g., some ShowAllInventory method)
    private readonly List<Item> inventoryItems;
    public Inventory()
    {
        inventoryItems = new List<Item>
        {
            // some predefined inventory slots with default inventory items
            new Chest(),
            new Helmet(),
            new Melee(),
            new Ranged()
        };
    }
    // these properties are required, if you want to access predefined 
    // inventory slots in strongly-typed manner; they are NOT required for comparison
    public Chest ChestSlot
    {
        get { return (Chest)inventoryItems[0]; }
        set { inventoryItems[0] = value; }
    }
    public Helmet HelmetSlot
    {
        get { return (Helmet)inventoryItems[1]; }
        set { inventoryItems[1] = value; }
    }
    public Melee MeleeSlot
    {
        get { return (Melee)inventoryItems[2]; }
        set { inventoryItems[2] = value; }
    }
    public Ranged RangedSlot
    {
        get { return (Ranged)inventoryItems[3]; }
        set { inventoryItems[3] = value; }
    }
    // The comparison.
    public void Compare(Item newItem)
    {
        foreach (var item in inventoryItems)
        {
            if (item.CanCompareWith(newItem))
            {
                item.CompareWith(newItem);
            }
        }
    }
}

请注意,内部库存使用集合来存储其项目。这允许对项目执行批处理操作(例如比较,以Compare方法实现)。

现在,让我们定义一些新类型的物品并测试我们的库存:

class SuperHelmet : Helmet
{
    public override int Defence
    {
        get { return 50; }
    }
}
class SuperMelee : Melee
{
    public override int Attack
    {
        get { return 200; }
    }
}

测试:

        var inventory = new Inventory();
        var superHelmet = new SuperHelmet();
        var superMeele = new SuperMelee();
        inventory.Compare(superHelmet);
        inventory.Compare(superMeele);