2011-04-04 23 views
9

我有点知道多态是什么,但没有清楚地理解它。也是我的代码如下:这是多态性的例子吗?

class Human 
{ 
    public virtual void CleanTheRoom() 
    { 
    } 
} 
class Woman:Human 
{ 
    public override void CleanTheRoom() 
    { 
    //women clean faster 
    } 
} 
class Man:Human 
{ 
    public override void CleanTheRoom() 
    { 
    //men clean slower, different code here 
    } 
} 
class Child:Human 
{ 
    public override void CleanTheRoom() 
    { 
    //empty ... children are lazy :) 
    } 
} 

我要解释这是因为polymorhism从基类人所有派生类包含方法CleanTheRoom但他们每个人它实现不同?

+1

更好的stil应该是把CleanTheRoom方法定义放在一个'IClean'接口中,并为那些可以清理的人类实现它。然后你就可以从这个界面中获得免费的多态主义。 – ChristopheD 2011-04-04 19:56:47

+29

这绝对是性别歧视的一个例子。 – juharr 2011-04-04 20:01:59

+1

@juharr和agism。 – kenny 2011-04-04 20:40:14

回答

21

多态性的好处来自于当你想在某种类型的Human上调用方法CleanTheRoom(),但你不关心哪一个具体。

由在基类水平,Human定义CleanTheRoom(),你可以在你的应用程序的其他地方写短的,更干净的代码,只要你用的Human实例的工作,无论是ManWomanChild

多态性,例如,可以让你避免难看的条件语句,你明确地检查每个类型的Human和调用不同的方法:

好:

private void SomeMethod(Human h) 
{ 
    //some logic 
    h.CleanTheRoom(); 
    //more logic 
} 

坏:

private void SomeMethod(Human h) 
{ 
    //some logic 
    if (h is Man) 
     CleanRoomSlowly(); 
    else if (h is Woman) 
     CleanRoomQuickly(); 
    else if (h is Child) 
     GoofOff(); 
    //some logic 
} 
+0

也是一个很好的答案,出于在JacobM评论中表达的相同原因。 – riwalk 2011-04-04 20:07:01

16

你有什么是一个很好的例子继承权。多态性特指能够通过使用单一类型(父类或接口)来引用不同类型的对象,这种类型的继承使这成为可能。像这样:

List<Human> humans = new ArrayList<Human>(); 

humans.add(new Woman()); 
humans.add(new Woman()); 
humans.add(new Man()); 
humans.add(new Child()); 
humans.add(new Child()); 

foreach(Human hum in humans) { 
    hum.CleanTheRoom(); //I don't know the type of hum, but I don't care 
} 

说我一直在收集来自不同地点的人的实例 - 我不知道每个人是什么类型。但是我仍然可以遍历它们并调用CleanTheRoom(),因为它们共享一个父类。

我会添加一个真实世界的例子。假设我有一个Invoice级别的不同类型的发票的各种子类别 - 可能有不同种类的服务客户Invoice与做一次性购买的客户。有时我很在乎差异,我只处理一种类型。但有时我想循环浏览本月的所有发票并打印出来。如果父类有一个print()方法(可能由不同类型实现的方法不同),那么我可以做到这一点。

+1

这在我看来是最好的答案。当你看到* *被使用时,多态性的价值就会变得明显,而不是当你看到它被定义*时。 – riwalk 2011-04-04 20:02:50

+0

我希望有一个简洁的术语来描述多态性的遗传。有一个吗? – Daisetsu 2011-04-05 21:52:17

+1

基于父类的多态性在计算机科学中有时被称为“子类型多态性”。在面向对象编程语言的背景下,我从来没有见过“多态”这个词用来指代除了多态的多态之外的任何东西(泛型也是一种多态的形式,从技术上说,但我们从来没有这样引用过) 。而从另一方面来说,我从来没有遇到过一种不允许多态的继承形式。所以在一个面向对象的上下文中,“多态”这个词似乎就足够了。 – 2011-04-06 20:57:38

0

是的,这是正确的。你可以调用CleanTheRoom()方法,而不必知道人类是哪一种人。

Here你有一些基本的例子。

0

我认为你没有看到好处,这是你错过了完全理解多态性的关键。我会试着举个例子:

假设你有一个简单的CRUD表单。这是保存按钮的代码:

var Client = PopulateDTO(); //put all the values in the controls, to an object 

if(Action==Actions.Create){ 
    _repository.Create(Client); 
} 
else if(Action==Actions.Update){ 
    _repository.Update(Client); 
} 
else if(Action==Actions.Delete){ 
    _repository.Delete(Client); 
} 

this.Close(); 

此代码有效,但代码错误,难以阅读。让我们用多态性(和策略模式):

public abstract class BaseStrategy{ 
    abstract void Do(ClientDto Client); 
} 

public class CreateStrategy:BaseStrategy{ 
    public override void Do(ClientDto Client){ 
    _repo.Save(Client); 
    } 
} 

public class UpdateStrategy:BaseStrategy{ 
    public override void Do(ClientDto Client){ 
    _repo.Update(Client); 
    } 
} 

public class DeleteStrategy:BaseStrategy{ 
    public override void Do(ClientDto Client){ 
    _repo.Delete(Client); 
    } 
} 

因此,我们有一个抽象类,和3个实现,每一个做一些与客户端对象。现在,保存按钮的形式的代码将是:

BaseStrategy stg = GetCorrectStrategy(); 

var Client = PopulateDTO(); 

stg.Do(Client); 

this.close; 

而且方法GetCorrectStrategy()将实例正确的战略实施,取决于如果用户创建,编辑或删除客户端。

我希望这个答案能帮到你。但如果没有帮助你,我建议你阅读关于战略模式,这是我认为多态性的最佳用法之一

0

由于几个人已经给出了多态性的好例子,我会提供一个不同的视角真的帮了我很多忙。

在函数式编程中,函数是第一类的概念,而对象是最高级的OOP。

多态性是OOP与FP匹配的模式。这是一个使用模式匹配的函数(使用ML样式语法)。

let f x = 
     match x with 
     | T -> //do stuff with a T to return some value 
     | S -> //do stuff with an S to return some value 
     | U -> //do stuff with a U to return some value 
     | V -> //do stuff with a V to return some value 

因此,当使用函数f,则可以将它传递任一类型的T,S,U,或V.在强类型FP语言如F#的目的,x的类型被表示为T|S|U|V。这种类型通常被称为总和类型或标签联合。

如果我们修正你的例子使得Human成为一个抽象类,那么很明显OOP中的多态只是给你一种表达和类型的方法。

因此,CleanTheRoom是一个函数,其类型为Human。但Human只是类型Man|Woman|Child这是一个总和类型的名称。像C#这样的语言和F#这样的功能语言之间的巨大差异在于,它将对象当作顶级事物,而另一些则把对象看作是顶级事物。而且,像C#这样的OOP语言中的所有内容都必须具有名称。在函数式语言中,我们可以表示Man|Woman|Child的类型,而不必明确地命名它。

的关键是不要想的代码具有不同CleanTheRoom方法,而是想作为CleanTheRoom一个方法,它采用一个型Man|Woman|Child(名为Human)的。多态性仅仅是实现细节。总之,多态(特别是抽象类)基本上只是给你一种命名求和类型和模式匹配的方法。

参见:

0

在C#中的一个例子:

这是我的类文件

class parent 
    { 
     public virtual string saySomething(string s) 
     { 
      return s+":Parent"; 
     } 
    } 
    class man : parent 
    { 
     public override string saySomething(string s) 
     { 
      return s+":Man"; 
     } 
    } 
    class woman : parent 
    { 
     public override string saySomething(string s) 
     { 
      return s+":Woman"; 
     } 
    } 
    class child : parent 
    { 
     public override string saySomething(string s) 
     { 
      return s+":Child"; 
     } 
    } 

创建四个按钮和一个标签。

下面是一个简单的Form1中

private void Form1_Load(object sender, EventArgs e) 
     { 
      p1= new parent();  

     } 

     private void button1_Click(object sender, EventArgs e) 
     {    
      label1.Text = p1.saySomething("I am parent!"); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      p1 = new man(); 
      label1.Text = p1.saySomething("I am man!"); 
     } 

     private void button3_Click(object sender, EventArgs e) 
     { 
      p1 = new woman(); 
      label1.Text = p1.saySomething("I am woman!"); 
     } 

     private void button4_Click(object sender, EventArgs e) 
     { 
      p1 = new child(); 
      label1.Text = p1.saySomething("I am child!"); 
     } 

的实现是它运行时多态性? P1是一个对象。根据情况(上下文),按下一个按钮,它执行不同的代码。因此,根据点击事件,p1的行为会有所不同。

+0

如果你看看这个例子,它是多态的。但是这个例子并没有真正展现多态的力量。 – 2012-10-10 20:42:16

0
class Program 
{ 
    static void Main(string[] args) 
    { 
     List<ICleanTheRoom> cleanerList = new List<ICleanTheRoom> 
      { 
       new Child(), 
       new Woman(), 
       new Man() 
      }; 
     foreach (var cleaner in cleanerList) 
     { 
      cleaner.CleanTheRoom(); 
     } 
    } 
} 

internal interface ICleanTheRoom 
{ 
    void CleanTheRoom(); 
} 

// No need for super type 

//class Human : ICleanTheRoom 
//{ 
// public virtual void CleanTheRoom() 
// { 
// } 
//} 


internal class Woman : ICleanTheRoom 
{ 
    public void CleanTheRoom() 
    { 
     throw new NotImplementedException(); 
    } 
} 

class Man: ICleanTheRoom 
{ 
    public void CleanTheRoom() 
    { 
     throw new NotImplementedException(); 
    } 
} 

class Child: ICleanTheRoom 
{ 
    public void CleanTheRoom() 
    { 
     throw new NotImplementedException(); 
    } 
}