2017-09-17 32 views
0

我发现,有可能创建一个子类的实例,并将其分配给类的父类的变量。我无法将这种情况包裹起来。在C#中的某些多态的说明

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

我有一个关于这几个问题:

  1. 这是什么意思,甚至?

  2. 可能的结果是什么?

  3. 为什么&什么时候有人会做这种东西?

父类:

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()); 
    } 
} 

回答

6

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

假设你拥有一个动物园。在这个动物园里面(显然)有一些动物。如果你想将它们全部存储在一个数组或列表中,你将不得不为它们使用base type,在这种情况下为Animal。现在,从我们的基类型Animal派生的类共享相同的属性,因此也是相同的方法。

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

现在让我们声明一个狮子的类。

class Lion : Animal 
{ 
} 

即使我们没有写Lion类中的方法ShoutLion实例必须提供给他们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对象,则只需从as运算符得到null

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"; 
    } 
} 

对于一个完整的回答你的问题,你应该看看在多态性的教科书或文章。

2

它甚至意味着什么?

Polymorphism - 装置许多变形装置形式

因此多态性具有许多形式装置。在面向对象的编程范例中,多态性通常表示为“一个接口,多个功能”。 - Tutorials Point

什么是可能的结果和

以及从您的代码:

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

输出将是:I am an animal

在这里,您所呼叫的Shout方法(孩子)的Species(父母亲)by instantiati ng h as of typeSpecies

为什么&时会有人做这样的东西

而且从你的例子,你可以调用Humanshout法的casting

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

帮助输出将是:I am an human

在这里,我做这个((Human)h)为更好的可读性也可以做h as Human铸造hHuman然后调用Human类的Shout方法。

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

检查Fiddle


PS:你也应该注意到什么@Willem说

你不应该使用新的。但使呼喊虚拟和


基本上多态性做是为了过载方法人力的怒吼使用倍率(检查重写和虚拟使用)的同名但具有不同的数据类型作为参数或不同的数据类型本身,子类内,父类或父子之间

0

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

对具有ProcessPicture覆盖的ImageProcess基类进行映像。

ProcessPicture可能会在审阅或删除其他程序中的数据之前进行裁剪和清理。程序将其发回,但这次ProcessPicture需要添加水印。

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

+0

我想,这在技术上是正确的,但并没有提供关于抽象如何与编程相关的很好的解释,也没有提供关于实际流程在代码形式或抽象的“业务示例”中看起来像什么的任何细节'形式。 – TylerH