繁体   English   中英

遍历父/子结构

[英]Looping through a parent / Child structure

我正在开发一款游戏,可以专门针对每个暴民的四肢,因此您可以瞄准头部,腿部...

我有这个构造函数:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Legs = new List<Leg> { new Leg(), new Leg() };
    this.Torso = new Torso();
    this.Arms = new List<Arm> { new Arm(), new Arm() };
    this.Heads = new List<Head>
    {
        new Head
        {
            Ears = new List<Ear> { new Ear(), new Ear() },
            Eyes = new List<Eye> { new Eye(), new Eye() }
        }
    };
}

所有这些ILimb都从接口ILimb继承。

能够绕过包括儿童在内的所有肢体的最佳方法是什么(如果适用)?

我可以添加一个protected List<ILimb> { get; set; } protected List<ILimb> { get; set; } protected List<ILimb> { get; set; } ,然后添加每个,但这是多余的。

有任何改进的想法或建议吗?

最好的方法是改用以下结构:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Limbs = new List<ILimb>();
    this.Limbs.Add(new Legs() { Limbs = new List<Limb>() { new Leg(), new Leg() });
    this.Limbs.Add(new Torso());
    this.Limbs.Add(new Arms() { Limbs = new List<Limb>() { new Arm(), new Arm() });
    this.Limbs.Add(new Heads() { Limbs = new List<Limb>() { new Head() { Limbs = new List<Limb>() .... , ... });
}

您可以整理代码,但基本上它应该具有四肢的集合,并且四肢应该具有四肢的集合,以便您可以具有Head> Ears> Ear或您想要的任何层次结构。

然后在您的ILimb界面中为其设置Limbs属性

public interface ILimb
{
    List<ILimb> Limbs { get; set; }
    List<ILimb> GetAllLimbs { get; }
}

并使用此方法创建抽象基类Limb:

public virtual GetAllLimbs()
{
// pseudocode: something like this (basically recurse through the children)
return this.Limbs().foreach (c => c.GetAllLimbs()).union(this.Limbs());
}

然后,它可以轻松地向下爬取层次结构并检索每个分支。

所以你可以做

myHumanoid.GetAllLimbs().Where(c => c is Arm).TakeDamage(5);

例如。

您为所有对象都拥有定制模型,除了一个...定制的模型集合 List<T>是一个好的开始,但是它没有您要寻找的功能。 尝试将功能添加到Humanoid但实际上并不属于其中。

实现这样的事情:

public class LimbList<T> : IList<T> where T : ILimb
{
    // implement IList<T> here
}

在这里,您将包括用于收集肢体的业务逻辑。 例如:

  • 如果支持集合中已经有2个Arm对象,则使用Arm对象调用.Add()时将引发异常。
  • 如果已经有1个Torso的支持集合对象,调用时抛出一个异常.Add()Torso对象。
  • 等等

Humanoid然后将具有LimbList<ILimb>属性:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null)
{
    this.Limbs.Add(new Leg());
    this.Limbs.Add(new Leg());
    this.Limbs.Add(new Torso());
    this.Limbs.Add(new Arm());
    this.Limbs.Add(new Arm());
    this.Limbs.Add(new Head
        {
            // as an added exercise, how would you extend this concept to the Head object?
        });
}

您可以轻松地遍历该列表:

foreach (var limb in this.Limbs)

从本质上讲,这里的重点是对象集合本身就是一个对象,具有与其他任何对象一样的自定义逻辑。 将对象逻辑放入对象中,将集合逻辑放入集合中。 没有规则说您只能使用框架中的内置集合。

给定legs列表和arms列表,您可以执行以下操作:

IEnumerable<ILimb> limbs = ((IEnumerable<ILimb>)arms).Concat(legs);

然后迭代它:

foreach (var limb in limbs) 
{
    // limb is an ILimb and you can access anything in that interface 
    // for each limb
}

另一种选择是,您可以像这样向Humanoid添加方法:

public IEnumerable<ILimb> GetLimbs() 
{
    foreach (var a in Arms)
    {
        yield return a;
    }
    foreach (var l in Legs)
    {
        yield return l;
    }
}

然后,您可以执行以下操作:

foreach(var limb in someHumanoid.GetLimbs()) 
{

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM