C#中某些多态行为的解释

时间:2017-09-17 10:16:36

标签: c# polymorphism

我发现可以创建子类的实例并将其分配给父类的变量。我无法绕过这种情况。

在我的代码中,虽然实例是Human类。它在控制台中记录“我是动物”

我对此有一些疑问:

  1. 它甚至意味着什么?

  2. 可能的结果是什么?

  3. 为什么&什么时候会有人做这种事情?

  4. 家长班:

    public class Species
    {
        public  String Shout()
        {
            return "I am an animal";
        }
    }
    

    儿童班:

    public class Human : Species
    {
        public new String Shout()
        {
            return "I am a Human";
        }
    }
    

    实例化:

    class Program
    {
        static void Main(string[] args)
        {
            Species h = new Human();
    
            Console.WriteLine(h.Shout());
        }
    }
    

4 个答案:

答案 0 :(得分:7)

如果要有效地使用面向对象编程或OOP,多态性非常有用。

假设您拥有一个动物园。在这个动物园里面(显然)有一些动物。如果您希望将它们全部存储在一个数组或列表中,则必须使用base type,在本例中为Animal。现在,从我们的基类型Animal派生的类共享相同的属性,因此也使用相同的方法。

class Animal
{
    public string Shout ()
    { 
        return "I am an animal!"; 
    }
}

现在让我们为狮子宣布一个班级。

class Lion : Animal
{
}

即使我们没有在Shout类中编写Lion方法,Lion的实例也会使用Shout方法可供他们使用,因为他们Animal类派生

但是如果我们希望Lion类与Shout有所不同呢?我们可以使用virtualoverride关键字。这些可用于属性和方法。 virtual表示可以覆盖 的方法或属性,而override执行实际覆盖。两者都需要为这个工作设置正确的位置。

要覆盖我们的Shout方法,我们必须先将其标记为virtual

public virtual string Shout () { ... }

现在,在我们的Lion课程中,我们可以对Shout方法执行覆盖。

public override string Shout ()
{
    return "Rooooaaar, I am a lion!";
}

现在我们澄清了这一点,让我们来看看它的一些用法。

Lion lion1 = new Lion();

这通过调用类的构造函数来创建Lion类的新实例。如果我们现在致电lion1.Shout(),我们会将"Rooooaaar, I am a lion!"作为返回值。

Animal animal1 = new Lion();

这也有效!由于我们的Lion类派生自基类型Animal,因此该对象可以存储在类型Animal的对象中。但不要被愚弄!如果我们现在致电animal1.Shout(),我们仍然会返回"Rooooaaar, I am a lion!"

Animal animal2 = new Animal();

这只是基类的一个实例,这意味着方法animal2.Shout()将返回"I am an animal!"

现在我们说我们还有更多动物,CatDogLion。不使用多态,我们无法将它们存储在单个数组中,因为它们没有任何共同之处!但是,如果它们来自Animal类,我们可以这样做:

List<Animal> animals = new List<Animal>();
animals.Add(new Cat());
animals.Add(new Dog());
animals.Add(new Lion());
animals.Add(new Animal());

以上所有这些都可以完美地运作!

最后,如果您要从此Animal列表中检索某个元素,并且想要在其上调用某些Dog特定方法,则可以(如果它实际上是Dog当然,使用animals[1] as Dog将其转换为Dog对象。但是,如果它不是Dog对象,您只需从null运算符返回as

答案 1 :(得分:2)

  

它甚至意味着什么?

Polymorphism - Poly 表示很多变体表示表单

因此多态意味着有许多形式。在面向对象的编程范例中,多态性通常表示为一个接口,多个函数&#39;。 - Tutorials Point

  

可能的结果是什么?

从您的代码开始:

Species h = new Human();
Console.WriteLine(h.Shout()); //calling Shout method of Species

输出结果为:I am an animal

通过在类型中实例化Shout,您在调用Species(子级)的Human(基本父级)的h方法Species

  

为什么&amp;什么时候会有人做这种事情

同样在您的示例中,您可以在shout

的帮助下调用Human casting方法
Console.WriteLine(((Human)h).Shout());  //calling Shout method of Human

输出结果为:I am an human

在此我将h作为Human投放((Human)h)以提高可读性,您也可以执行h as Human,然后调用Shout Human方法{1}}课程。

Console.WriteLine((h as Human).Shout());  //calling Shout method of Human

检查Fiddle

PS:您还应该注意@Willem所说的

  

你不应该使用新的。但要使Shout成为虚拟并在人类的呐喊中使用覆盖

基本上多态性是针对重载方法(检查覆盖和虚拟用法)进行的,但是具有不同的数据类型作为参数或不同的数据类型本身,在子类,父类或子和父之间

答案 2 :(得分:1)

不完全回答您的问题,但如果您希望代码显示“我是人”,请执行以下操作:

家长班:

public class Species
{
    public virtual  String Shout()
    {
         return "I am an animal";
     }
  }

儿童班:

 public class Human : Species
 {
    public override String Shout()
    {
         return "I am a Human";
     }
}

要完整回答您的问题,您应该查看有关多态性的教科书或文章。

答案 3 :(得分:0)

作为一个商业示例,您正在编写一个程序,您需要对某个对象执行特定操作。该对象之前可能已通过此程序,但需要采用不同的路径。您可以将其设置为使用多态并覆盖您需要更改的方法。例如:

对ImageProcess的基类进行成像,该基类具有ProcessPicture的覆盖。

ProcessPicture可能会在审核之前进行一些裁剪和清理,或者在另一个程序中从中提取数据。程序将其发回,但这次ProcessPicture需要添加水印。

通过这种方式,我们可以让一个程序根据图像的状态执行不同的任务。