我知道什么是多态,但却无法清楚地理解它。我的代码也是如下:
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 :)
}
}
我是否应该解释这是多态的,因为基类Human中的所有派生类都包含方法CleanTheRoom但是它们中的每一个都以不同的方式实现?
答案 0 :(得分:21)
当您想要在某种类型的CleanTheRoom()
上调用Human
方法时,多态性的好处就出现了,但您并不关心哪一种具体。
通过在基类级别CleanTheRoom()
定义Human
,只要您使用Human
的实例,就可以在应用程序的其他位置编写更简洁,更清晰的代码,无论是是Man
,Woman
或Child
。
多态性允许您避免丑陋的条件语句,其中您明确检查每种类型的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
}
答案 1 :(得分: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()
方法(可能由不同类型实现不同),那么我可以这样做。
答案 2 :(得分:0)
是的,这是正确的。你可以调用方法CleanTheRoom(),而不知道它是什么样的人类。
Here你有一些基本的例子。
答案 3 :(得分: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()方法将实例化正确的策略实现,具体取决于用户是否正在创建,编辑或删除客户端。
我希望这个答案会对你有所帮助。但如果没有帮助你,我建议你阅读一下策略模式,在我看来,这是多态性的最佳用途之一
答案 4 :(得分: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
。这些类型通常称为Sum类型或Tagged Unions。
如果我们修改你的例子以使Human
成为一个抽象类,那么很明显OOP中的多态性只是为你提供了一种表达和类型的方法。
因此,CleanTheRoom
是一个采用Human
类型的函数。但Human
只是类型Man|Woman|Child
的名称,它是和类型。像C#这样的语言和像F#这样的函数语言之间的巨大差异在于,一个人将对象视为顶级事物,而另一个人将函数视为顶级事物。而且,像C#这样的OOP语言中的所有内容都必须具有名称。在函数式语言中,我们可以表示类型Man|Woman|Child
,而无需明确命名它。
关键是不要将代码视为具有不同的CleanTheRoom
方法,而是将CleanTheRoom
视为采用类型Man|Woman|Child
的一种方法(名为{{1} }})。多态性只是实现细节。
总之,多态(特别是抽象类)基本上只是为您提供了一种命名和类型并进行模式匹配的方法。
请参阅:
答案 5 :(得分: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的行为会有所不同,具体取决于点击事件。
答案 6 :(得分: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();
}
}
答案 7 :(得分:0)
它是每次在运行时创建的新对象,显然继承但没有多态。