在c#中创建继承类的对象

时间:2017-02-20 01:38:05

标签: c# oop

这应该是一个非常直截了当的问题。我只要求一个简单 易于理解的答案。不,我不想要教科书定义或文档链接,请尽可能简单地回答。

请考虑以下事项:

class Monster
{
    public int Hp { get; protected set; }
    public string Name { get; protected set; }

    public virtual void Attack()
    {
        Console.WriteLine("Monster attacking!");
    }
}

class Skeleton : Monster
{
    public Skeleton()
    {
        Hp = 20;
        Name = "Skeleton";
    }
    public override void Attack()
    {
        Console.WriteLine("Skeleton attacking!");
    }
}

现在想象一下我用Monster这样的类型创建一个新的Skeleton对象。

 Monster skeleton = new Skeleton();

我想知道使用怪物类型创建一个Skeleton对象与使用 Skeleton类型创建一个Skeleton对象之间的区别。

 Skeleton skeleton = new Skeleton();

我不明白这两者之间是否存在差异,或者它是如何起作用的。任何和所有帮助表示赞赏!谢谢!

3 个答案:

答案 0 :(得分:3)

当您想要在一个集合中保留多个怪物时,创建具有Skeleton类型的Monster对象的好处会变得更加明显。

例如,您可能有一个如下定义的列表:

List<Monster> EncounterMonsters = new List<Monster>();

Skeleton对象声明为Monster,您可以将其添加到此列表中,以及您创建的任何其他Monster类。

所以,你可能还有另一个怪物类:

class Ogre : Monster
{
    public Ogre()
    {
        Hp = 50;
        Name = "Ogre";
    }

    public override void Attack()
    {
        Console.WriteLine("Ogre attacking!");
    }
}

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

Monster skeleton = new Skeleton();
Monster ogre = new Ogre();

EncounterMonsters.Add(skeleton);
EncounterMonsters.Add(ogre);

然后,这将允许您循环使用EncounterMonsters集合并使用每个使用重写的Attack方法进行攻击。

答案 1 :(得分:1)

要扩展已接受的答案,不同之处在于,如果使用基类Monster实例化对象,则只有Monster类公开的属性和方法可用。

考虑一下:

public class Monster
{
    public Monster(int hp, string name)
    {
        Hp = hp;
        Name = name;
    }
    public int Hp { get; protected set; }
    public string Name { get; protected set; }
}

public class Skeleton : Monster
{
   public string Loot { get; set; } // <- Note added property.
   public Skeleton(int hp, string name) : base(hp, name)
   {
       Loot = "Sword";
   }
}

public class Vampire : Monster
{
    //- some vampire specific properties

    public Vampire(int hp, string name) : base(hp, name)
    {
      // ...
    }
}

现在,如果你将骨架实例化为怪物。

Monster skeleton = new Skeleton(100, "skully");
skeleton.Loot(); //- Will throw a compile time error.

如果将其实例化为Skeleton;

Skeleton skeleton = new Skeleton(100, "skully");
skeleton.Loot(); // Will return "Sword";

例如,当你有一个方法或服务对你的怪物的常见属性起作用时,这很有用,比如你有一个记录怪物统计数据的方法。

public string LogMonsterStats(Monster monster)
{
    return $"{monster.Name} has {monster.Hp} health points";
}

///....

Skeleton skeleton = new Skeleton(100, "Bob");
LogMonsterStats(skeleton); // returns "Bob has 100 health points"

请注意,我们正在将Skeleton实例传递给需要Monster实例的方法。因此,在方法的范围内,Bob被视为怪物,而不是骷髅。

答案 2 :(得分:0)

我们知道,派生类可以借助“ Base()”方法调用基类构造函数。 初始化基类成员 初始化子类的类成员

我们没有办法从错误的基类中调用派生的调用构造函数。