在我的游戏中,我有一个Loot的基类,它具有通用的任何方法,可以由玩家拾取并存储在他的库存中.这将包括药水,装备,弹药等.我可以装备箭,但不是魔药.因此,Arrow将成为Ammo的子类,最终将来自Loot.我可以喝药水而不是箭.因此,Potion会将Loot子类化,但实现IConsumeable.等等.
Loot对象具有Quantity属性(10个箭头; 2个药水).在我的Loot类中,我有一个名为Split的方法,它允许玩家获取项目的“堆叠”(如箭头)并将其拆分为两个单独的堆栈.因此,它将Arrow实例的数量减少一定量,然后返回一个新的Arrow实例,其数量值=从原始实例中获取的值.
我的想法是我在Loot中编写方法,因为任何Loot都可以堆叠,只要它的int StackLimit属性大于1.在按照指定的数量递减调用Loot之后,我将返回一个相同的新对象类型.问题是,我不知道该对象将是什么类型的Loot子类.
public abstract class Loot
{
public int Quantity { get; set; }
public Loot Split(int quantityToTake)
{
Loot clone = (Loot)this.MemberwiseClone();
//RestrictNumberToRange(int min, int max, int value) is a delegate which clamps a value to min,max
this.Quantity -= Utility.RestrictNumberToRange<int>(1, this._quantity - 1, quantityToTake);
clone.Quantity = quantityToTake;
return clone;
}
}
这是一个非常糟糕的方式来解决这个问题吗?我想到了反思,但我听到在这样的情况下是否使用它的意见不一.
有没有办法定义处理this.FurthestSubClass的方法?
我知道我的子类可能有不同的构造函数,所以尝试返回’new this.FurthestSubclass()’可能是不可行的,因为我不知道如何构造它.但我希望能够处理它的Loot方法,所以我使用Loot作为返回类型.
最佳答案 我认为这是仿制药的一个很好的例子.尝试在Loot中重写你的split方法,如下所示:
public TLoot Split<TLoot>(int quantityToTake) where TLoot : Loot
{
TLoot clone = (TLoot)this.MemberwiseClone();
...
return clone;
}
这应该照顾打字问题.
编辑添加:构造函数问题更有趣,但您可能会发现无参数构造函数与对象初始化器结合使用.如果您修改约束,如下所示:
public TLoot Split<TLoot>(int quantityToTake) where TLoot : Loot, new(TLoot)
{
// stuff
TLoot newLoot = new TLoot();
...
return newLoot;
}
“new(T)”约束允许您基于泛型类型创建新对象.
进一步编辑:我应该在这个上下文中给出一个对象初始化器的例子:
TLoot newLoot = new TLoot { Quantity = quantityToTake };
这假定Loot有一个名为Quantity的公共属性.对象初始值设定项可以为具有公共集{}的任何公共属性设置值;