Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 返回基类的任意子类的基类方法_C#_Inheritance_Clone - Fatal编程技术网

C# 返回基类的任意子类的基类方法

C# 返回基类的任意子类的基类方法,c#,inheritance,clone,C#,Inheritance,Clone,在我的游戏中,我有一个基本的战利品类,它有一个通用的方法,可以被玩家拾取并存储在他的库存中。这包括药剂、装备、弹药等。我可以装备箭,但不能装备药剂。所以箭是弹药的一个子类,它最终会从战利品中衍生出来。我能喝药剂,但不能喝箭。所以魔药将成为战利品的子类,但实现IConsumeable。等等 战利品有数量属性(10支箭;2种药剂)。在我的战利品类中,我有一个名为Split的方法,允许玩家获取一堆物品(如箭头),并将其分成两个独立的堆叠。因此,它将Arrow实例的数量减少一定量,然后返回一个新的Arr

在我的游戏中,我有一个基本的战利品类,它有一个通用的方法,可以被玩家拾取并存储在他的库存中。这包括药剂、装备、弹药等。我可以装备箭,但不能装备药剂。所以箭是弹药的一个子类,它最终会从战利品中衍生出来。我能喝药剂,但不能喝箭。所以魔药将成为战利品的子类,但实现IConsumeable。等等

战利品有数量属性(10支箭;2种药剂)。在我的战利品类中,我有一个名为Split的方法,允许玩家获取一堆物品(如箭头),并将其分成两个独立的堆叠。因此,它将Arrow实例的数量减少一定量,然后返回一个新的Arrow实例,其数量值=从原始实例获取的数量值

我的想法是,我将在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;
    }
}
公共抽象类战利品
{
公共整数数量{get;set;}
公共战利品分割(int quantityToTake)
{
Loot clone=(Loot)this.MemberwiseClone();
//RestrictNumberToRange(int-min,int-max,int-value)是将值钳制为min,max的委托
this.Quantity-=Utility.RestrictNumberToRange(1,this.\u Quantity-1,quantityToTake);
clone.Quantity=quantityToTake;
返回克隆;
}
}
这样做真的很糟糕吗?我考虑过反思,但对于是否在这种情况下使用它,我听到了各种不同的意见

是否无法定义处理此.FurthestSubClass的方法


我知道我的子类可能有不同的构造函数,所以尝试返回'newthis.FurthestSubclass()'可能是不可行的,因为我不知道如何构造它。但是我希望能够处理它的Loot方法,所以我将Loot用于返回类型。

我认为这是泛型的一个很好的例子。尝试在战利品中重写你的分割方法,如下所示:

public TLoot Split<TLoot>(int quantityToTake) where TLoot : Loot
{
    TLoot clone = (TLoot)this.MemberwiseClone();
    ...
    return clone;
}

这假设战利品有一个称为数量的公共属性。对象初始值设定项可以为任何具有公共
set{}的公共属性设置值

如果我是对的,唯一的一个小缺点是,您必须明确地提到您正在拆分的
TLoot

Arrow arrow1;
/* some code initializing arrow1 */
Arrow arrow2 = arrow1.Split<Arrow>(10);

好的,这里的好处仍然很差(
Treasure.Arrows.Split(10+p.Age+p.Experience*2)
同样有效,而且更短!),但确实存在一些情况,使得返回类型隐式化极大地提高了可读性。

你知道,我最近刚听了一些关于这方面的解释,我想我明白了。很明显,我还没有达到禅宗的境界。我来试试,谢谢。所以,需要明确的是:如果这个实例是一支箭,它来自于弹药,它来自于战利品,拆分方法将返回一支箭?@Super,是的,这是正确的。仿制药真是太棒了!正如我所说,我以前见过这个(事实上,我的示例中的代表使用了它),但是看到它在这里的应用真的让我大开眼界-谢谢,伙计。
TLoot newLoot = new TLoot { Quantity = quantityToTake };
Arrow arrow1;
/* some code initializing arrow1 */
Arrow arrow2 = arrow1.Split<Arrow>(10);
/*Given an certain among of arrows found in the treasure chamber,
  each player in the team receives a fraction of it according to his age
  and experience, but always 10 arrows at least anyway.
  Ok, ok ! I had to search before finding such an example vaguely accurate
  in the context of arrows and potions ! lol*/
foreach(Player p in Team)
   p.Arrows = Treasure.Arrows.Split<Arrow>(10).Split<Arrow>(p.Age).Split<Arrow>(p.Experience*2);

foreach(Player p in Team)
   p.Arrows = Treasure.Arrows.Split(10).Split(p.Age).Split(p.Experience*2);