创建<base class>类型的变量以在C#中存储<derived class>对象

dhu*_*s01 19 c# polymorphism inheritance class object

我对编程有些新意,我对C#中的类,继承和多态有疑问.在了解这些主题的同时,我偶尔会遇到类似这样的代码:

Animal fluffy = new Cat();  // where Animal is a superclass of Cat*
Run Code Online (Sandbox Code Playgroud)

这让我很困惑,因为我不明白为什么有人会创建一个类型为Animal的变量来存储Cat类型的对象.为什么一个人不会简单地写这个:

Cat fluffy = new Cat();
Run Code Online (Sandbox Code Playgroud)

我确实理解为什么将子对象存储在父类型变量中是合法的,但不是为什么它有用.是否有充分的理由将Cat对象存储在Animal变量与Cat变量中?一个人可以举个例子吗?我确定它与多态和方法覆盖(和/或方法隐藏)有关,但我似乎无法绕过它.提前致谢!

Say*_*yse 19

我能给你的最简单的例子是你想要一份所有动物的清单

 List<Animal> Animals = new List<Animal>();
 Animals.Add(new Cat());
 Animals.Add(new Dog());
Run Code Online (Sandbox Code Playgroud)

如果您曾经使用Winforms创建了一个项目,那么您将使用类似的东西,因为所有控件都来自Control.然后您会注意到一个Window有一个控件列表(this.Controls),它允许您一次访问窗口上的所有子控件.IE隐藏所有控件.

 foreach(var control in this.Controls)
      control.Hide();
Run Code Online (Sandbox Code Playgroud)

  • 这解释了协方差,但它并不是OP所要求的. (4认同)
  • +1新手的美丽例子 (3认同)

Hen*_*man 14

但不是为什么它有用.

看看一些更好的例子:

Cat myCat = new Cat();
Dog myDog = new Dog();

List<Animal> zoo = ...;  // A list of Animal references
zoo.Add(myCat);          // implicit conversion of Cat reference to Animal reference
zoo.Add(myDog);
Run Code Online (Sandbox Code Playgroud)

void CareFor(Animal animal) { ... }
CareFor(myCat);         // implicit conversion of Cat reference to Animal reference
CareFor(myDog);
Run Code Online (Sandbox Code Playgroud)

这种模式Animal fluffy = new Cat();在实际代码中并不常见(但确实会发生).

考虑一下非常简化的代码,它显示某些功能的工作原理,并且总能很好地展示该功能的原因.


Dav*_*huu 6

让我们看一个实际但极端的例子.

class Animal { }
class Bird : Animal { }
class Cat : Animal { }
class Dog : Animal { }
class Elephant : Animal { }
class Fennec : Animal { }
Run Code Online (Sandbox Code Playgroud)

假设我们有一个Person类.我们如何存储他唯一和独特宠物的参考?


方法1:疯狂的方式

class Person
{
    public Bird myBird;
    public Cat myCat;
    public Dog myDog;
    public Elephant myElephant;
    public Fennec myFennec;
}
Run Code Online (Sandbox Code Playgroud)

在那个烂摊子里,我们如何找回宠物?

   if (myBird != null)
    {
        return myBird;
    }
    else if (myCat != null)
    {
        return myCat;
    }
    else if (myDog != null)
    {
        return myDog;
    }
    else if (myElephant != null)
    {
        return myElephant;
    }
    else if (myFennec != null)
    {
        return myFennec;
    }
    else
    {
        return null;
    }
Run Code Online (Sandbox Code Playgroud)

我在这里很好,只有5种动物.假设我们有超过1000种动物.你是那个在Person类中编写所有变量的人,并在你的应用程序中的所有位置添加所有那些'if()'吗?


方法2:更好的方法

class Person
{
    public Animal myPet;
}
Run Code Online (Sandbox Code Playgroud)

这样,由于多态性,我们对这个人的宠物有了独一无二的独特参考,为了得到宠物,我们只需写:

return myPet;
Run Code Online (Sandbox Code Playgroud)

那么,做事的最佳方式是什么?方法1还是2?