我无法达成一种方法(图片)

时间:2015-12-10 23:53:35

标签: c# class methods subclass

我正在创建一个游戏以学习C#编程。

我有一个名为Unit的班级和两个派生类型,WolfSpider

我还创建了一个名为UnitList的类,其中包含List<Unit>我要存储Unit个实例的位置。

还有另一个名为Battle的类,其中一个方法循环遍历Unit中的每个List<Unit>。我想基于Type的{​​{1}}使用不同的方法,无论是Unit还是Wolf

请参阅下图,因为我不擅长解释概念;我已经坚持了几天。

Image

2 个答案:

答案 0 :(得分:1)

您可能正在寻找的是c#is运营商。

例如

if(unit is Wolf)
{
    // Do something
}
else if (unit is Spider)
{
    // Do Something
}

C# is operator on MSDN

进入这些区块后,您可以使用类型转换来调用方法。

if(unit is Wolf)
{
    ((Wolf)unit).WolfAttack();
}

但是,使用您已经设置的继承树,在C#中有一种更清晰的方法。

class Unit
{
    public virtual void Attack()
    {
        Console.WriteLine("Unit attacks!");
    }
}

class Wolf : Unit
{
    public override void Attack()
    {
        Console.WriteLine("Wolf attacks!");
    }
}

class Spider : Unit
{
    public override void Attack()
    {
        Console.WriteLine("Spider attacks!");
    }
}

通过将Unit上的方法标记为virtual,您可以覆盖从Unit继承的类的行为。因此,现在调用攻击的代码就变成了

foreach(Unit unit in team1.GetList())
{
    unit.Attack();
}

因为它会为每个Attack()调用正确的Unit函数,无论是Spider还是Wolf

还有一个替代方案,那就是使用Interfaces。如果SpiderWolf类之间没有共享实现,这通常是一种很好的方法,而不是使用abstract类。

您可以定义IUnit接口,例如

public IUnit
{
    int Health { get; set; }
    void Attack();
}

然后,不是继承Unit,而是实施IUnit

class Wolf : IUnit
{
    public int Health { get; set; }

    public void Attack()
    {
        Console.WriteLine("Wolf attacks!");
    }
}

class Spider : IUnit
{
    public int Health { get; set; }

    public void Attack()
    {
        Console.WriteLine("Spider attacks!");
    }
}

然后,您可以使用IUnit代替Unit

这两种方法都是有效的,都有优点和缺点。允许类实现许多接口,但只继承一个类。接口无法定义功能,因此无法完全替换继承。还有更多,但这是两者之间最基本的区别。

答案 1 :(得分:1)

您正在尝试将System.Typeinstance进行比较。您要做的是使用typeof运算符或is/as构造用于C#。相反,为了获得更好的解决方案,您可以使用继承。

您可以将Unit类声明为抽象:

abstract class Unit
{
    private int health;
    private int damage;

    protected Unit()
    {
        health = 100;
    }

    public abstract void Attack();
}

虽然你的狼课可能是:

class Wolf : Unit
{
    public override void Attack()
    {
        // Do Something...
    }
}

然后,您可以从列表中检索每个Unit个实例并致电Unit.Attack();,然后调用相应的Attack()