我可以使用主类对象作为参数来查找子类对象吗?

时间:2018-02-12 14:13:27

标签: c# class casting type-conversion

我仍然有点新编码所以我想知道它是否/如何运作?

//a class with armor with subclasses to say what part of the body it go's
public class Armor
{
    //stuff that applies to all armor          
}
public class HeadArmor : Armor
{
    //stuff for HeadPieces only
}
public class ChestArmor : Armor
{
}
 //etc

//the class that stores what  armor is equiped
public class MainCharacterEquipment
{
    //the class of my maincharacter
    public MainCharacter HeroEquipment { get; set; }

    public HeadArmor HeadSlot { get; set; }
    public ChestArmor ChestSlot { get; set; }
    //etc
    //a constructor that sets all to null

    public void EquipArmor(Armor armor)
    {
        if (armor is HeadArmor)
        {
            HeadSlot = armor; //compile error
        }
        if (armor is ChestArmor)
        {
            ChestSlot = armor; //compile error -> Missing a cast?
        }
        //etc
    }
}

如果我这样做,它会问我是否错过了演员阵容。 从阅读这个论坛看来,子类似乎是主类的一种类型 但不是相反。

为了解决这个问题,我可以为每个盔甲子类制作一个方法。 我不使用(护甲盔甲)作为参数,而是使用(HeadArmor headArmor),(ChestArmor chestArmor)等... 但这似乎很乏味。 我还读到typeof()之间存在差异,但我也不理解。 我最好将对象装甲投射到它的子类。当然,if函数应检查它是否已经是子类(如果有意义的话)

ps:实际上没有Armor物体的实例。仅实例化子类的对象。 (这应该重要)

2 个答案:

答案 0 :(得分:3)

执行作业时,您需要指定相同的演员表。一旦初步检查通过,编译器就不会通过if语句携带信息。

在您的代码中:

if (armor is HeadArmor) // The compiler verifies this is HeadArmor
{
    // The compiler does not carry the information forward.
    // It has no way of knowing, on this line, that armor is still HeadArmor.
    // For all it knows, armor  could be ChestArmor which would be invalid.
    HeadArmor = armor; 
}

要修复错误,您需要按如下方式更新代码:

if (armor is HeadArmor)
{
    HeadArmor = (HeadArmor)armor; // Lets the compiler know this is HeadArmor.
}

另一种选择可能是使用as来尝试找出正确的选择。

var headArmor = armor as HeadArmor;
if (headArmor != null)
{
    HeadArmor = headArmor;
}

答案 1 :(得分:3)

我建议使用访客模式:

public void EquipArmor(Armor armor)
{
     armor.Equip(this); 
}

然后您的MainCharacterEquipment代码归结为:

net install

这摆脱了" if-else"如果您以后选择添加更多类型的装甲和插槽,则不需要触摸该代码。只需添加另一个XXXXArmor类,它就会转到正确的插槽。