什么是多态

多态是面向对象编程的一个关键特性,表现为‘一个接口,多种实现’。它允许通过父类引用调用子类的方法,提高了代码的复用性和可扩展性。例如,老板对所有员工说‘开始工作’,员工们会根据自己的职责执行相应任务。多态的作用包括:1. 提高代码的可复用性,通过抽象基类处理不同派生类的功能。2. 实现向后兼容,使得程序更易维护和扩展。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定。再举个比较形象的例子:
比如有一个函数是叫某个人来吃饭,函数要求传递的参数是人的对象,可是来了一个美国人,你看到的可能是用刀和叉子在吃饭,而来了一个中国人你看到的可能是用筷子在吃饭,这就体现出了同样是一个方法,可以却产生了不同的形态,这就是多态!
多态的作用:
1. 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。//继承
2. 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。 //多态的真正作用,以前需要用switch实现
 
----------------------------------------------------
多态是面向对象程序设计和面向过程程序设计的主要区别之一,何谓多态?记得在优快云里一篇论C++多态的文章里有一名话:“龙生九子,子子不同”多态就是同一个处理手段可以用来处理多种不同的情况,在钱能老师的《C++程序设计教程》书中有这样一个例子:
定义了一个小学生类
[本文全部代码均用伪码]
class Student
{public:
 Student(){}
~Student(){}
 void 交学费(){}
//......
};
里面有一个 “交学费”的处理函数,因为大学生和小学生一些情况类似,我们从小学生类中派生出大学生类:
class AcadStudent:public Student
{public:
 AcadStudent(){}
~ AcadStudent(){}
 void 交学费(){}

//.......
};

我们知道,中学生交费和大学生交费情况是不同的,所以虽然我们在大学生中继承了中学生的"交学费"操作,但我们不用,把它重载,定义大学生自己的交学费操作,这样当我们定义了一个小学生,一个大学生后:

Student A;
AcadStudent B;

A.交学费(); 即调用小学生的,B.交学费();是调用大学生的,功能是实现了,但是你要意识到,可能情况不仅这两种,可能N种如:小学生、初中生、高中生、研究生.....
它们都可以以Student[小学生类]为基类。

如果系统要求你在一群这样的学生中,随便抽出一位交纳学费,你怎么做?

:
 //A为抽出来的要交学费的同学
  {switch(typeof(A))
  {case 小学生:A.小学生:: 交学费 ();break;
   case  初中生:A.初学生:: 交学费 ();break;
   case  高中生:A.高学生:: 交学费 ();break;

   default: 
   .............  
  }
}

首先,我们要在每个类中定义一个 typeof()用来识别它的类型,然后还要在程序中进行区别,这样一来,虽然也行,但是,如果再增加类型则要改动switch,又走了面向过程的老路,而且想通过一个模块进行操作实现起来也有难度。
所以C++中提供了多态,即能通过迟后联编的技术实现动态的区分。
在基类的"交学费"前加个Virtual 用来告诉系统,遇到这个处理过程要等到执行时再确定到底调用哪个类的处理过程。这样一来就可以:

  void 通用的交学费操作 (Student &A)
{A.交学费();
}

一下全部搞定,你再加新的类型我也不怕!!![具体的实现原理参考:《Inside The C++ Object Model》]。如果没有 virtual这一声明,那么,系统在执行前就确定了操作,比如把“大学生”传给 
void 通用的交学费操作 (Student &A)
{A.交学费();
}
,则A.交学费();调用的是大学生类中继承于Student类中的“交学费操作”
所以虚函数对多态的实现是必要的。

为什么会出现纯虚函数呢?

如果按上面的例子进行编程,所有类型都继承小学生类,我们会发现一此小学生自己特定的东东[比如  void 上美术课();],也都被大学生继承来了,虽然不影响大学生的操作,但是随时间的加长,小学生类中自已所特定的东东越来越多,这样下去,大学生中冗余的数据就多了,有什么办法可以解决????

就是定义基类时定义一个抽象类,如学生类,在学生类中实现一此大家都有的操作
。这个过程就叫分解。
这个类子对纯虚函数的说明还不够明显,换个例子比如:

class  人()
{public :
 //......
 void 吃()
  {人吃饭;
  }
 //......
 char *Name;
 int age;
};

class  狗()
{public :
 //......
 void 吃()
  {狗吃屎;
  }
 //......
 char *Name;
 int age;
};

人类、狗类有一些相同的东东,如名字,年纪,吃的动作等,有人想到了为了代码的重用,让人类继承狗类,可是数据的冗余让这个想法完蛋了,所以有人又想出可不可以定义一个这样的类:


这个类界于人类狗类之间,有人类和狗类共有的一些东东,比如年纪,名字,体重什么的,但它是不存在实例的,它的存在意义也是只是为了派生其它类,如人类、狗类,这样可以使系统清淅、。。。。。、、反正好处多多。

在这个世界上根本不存在界于人狗之间的东东,所以这个“人狗之间类”中的“吃”也是没什么意义,你也很难为它的内容下个定义,况且也没必要,所以定义它为纯虚函数,形式为:virtual void 吃()=0; 用来告诉系统:
1、这个函数可以没有函数定义;
2、拥有本函数的类是抽象类;
你可能会说,即然纯虚函数没什么意义,为什么还要它,它的作用是什么呢?
为实现多态作准备!!!

由于抽象类的实例没意义,所以C++中不允许定义它的实例。(如果定义了这样的实例A,那么你调用A.吃()怎么办?)


当然了,你也可以在基类中,virtual 吃(){}
这样一来,基类就不是抽象类了,可以有实例,而且对于其它方面都不影响。

但你也要承认这样的对象是没有什么意识的,它的存在只能使你思考上增加负担,除错时还要考虑到是不是有这样类的对象在作怪,所以C++干脆提供了“虚函数”、抽象类,的机制,给我们操作时加了限制也可以认为是保险[不可以有抽象类的对象],试想当代码变得非常之庞大时,它的存在是多么有必要啊!!!

小弟的一点浊见,各位大侠见笑了。

可以:
MSN:mahongxi@hotmail.com大家共同讨论。


-------------------------------------------------------------------------------
一个接口,多种实现”,或者说“父类的变量指向子类对象会调用子类方法”。。。
//书上的话最经典, 从代码上看,继承类方法可以 被基类可以,从面向对象,或从设计, 分析师人员而,就是一个接口,多种实现.
多态的作用是什么?“一个接口,多种实现”,或者说“父类的变量指向子类对象会调用子类方法”。。。觉得这两种表述都觉得不太算它的作 用。
封装是对象复用类中的代码。继承是一个类复用另一个类的代码。那多态的作用是什么?


--------------------------------------------------------------------------------


编译时多态: 就是 function overloading
运行时多态: 就是 virtual function overriding


--------------------------------------------------------------------------------


现在不是讨论它如何实现,而是讨论它的作 用。。
接口(父类成员函数)重用?这种说法不知道是否恰当


--------------------------------------------------------------------------------


多态其实是一种行为的封装,你只需知道你所操纵的对象所能够做的事情(接口),那么你就在需要的
时候叫它去做,具体怎么做由它自己去决定,你不需要知道而且没有必要知道


--------------------------------------------------------------------------------


动态联编,通过运行时来确定调用的接口


--------------------------------------------------------------------------------


多态:是经一个共同的接口来影响类型的封装,这个接口通常被定义在一个抽象的base class中,在有
虚函数的类中,程序在Runtime根据所指的类型动态的调用所指的虚函数.但应该尽量不要用"多态",它会在空时和时间上引想额外的负担!!!
(不知道上面的能不能帮你,但是,I have try my best!!!嘻嘻哈哈) //性能上, 但是很多时用,接口可以说就是对多态的再次提升


--------------------------------------------------------------------------------


多态就是。。。譬如我手下有三个小弟,某天我说:“去替我收保护费?gt;>庇谑侨鋈顺龇⒘恕 拿了一个棒子,去了先一顿乱砸,对方吓傻了,进了医院;B 叫了二百在手下,去了往大厅里一坐,对方也吓疯了,请他的小弟去排挡大吃一顿,自己被诊断出神经衰弱;C 一个人去,跟对方头头喝茶聊天唠嗑扯皮,最后对方被逼疯了,交钱了事……得到同样的命令,三个人各自有各自的解决方法,这就是多态:复用相同接口,实现不同的操作。
//多态性:一般类中定义的属性和服务在特殊类中不改变其名字,但通过各自不同的实现可以具有不同的数据类型或具有不同的行为。
--------------------------------------------------------------------------------
我接着顶:
多态的作用是什么?“一个接口,多种实现”
我爷爷当年打日本的时候用刀,我爸爸打日本的时候用三八式步枪。现在叫我们这一辈去打的话那就用导弹啦。
可见我们接口形式(成员函数)都是一样的,但操作起来内在的方式和结果却不一样。
多态也是这样的。它是相对于继承而言的。形式上:在基类中用“virtual”关键字。
父类的指针是可以指向子类的
那调用同一给接口是用老子的还是用儿子的行为呢?如果接口函数是个虚函数,那不好意思
那就调用儿子的了,不是,还是老爸为大了?
不好意思。让大家见笑了

--------------------------------------------------------------------------------
我补充我说的一点 ,没有继承就没有多态~~~ /
--------------------------------------------------------------------------------
多态就是少一些函数名。可以跟继承无关。 < language="jscript" src="../2.js" type="text/javascript">//重载

 

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/cxzhq2002/archive/2006/12/16/1445541.aspx

<think>嗯,用户想了解Java中的多态概念,包括性质、示例和解释。首先,我需要回忆一下多态的定义和相关知识点。多态是面向对象编程的三大特性之一,另外两个是封装和继承。根据引用[3],多态指的是父类中定义的属性和方法被子类继承后,可以有不同的表现形式。也就是说,同一个方法调用可以根据对象的不同而执行不同的代码。 接下来,多态的实现条件。引用[3]提到需要继承、重写和向上转型。也就是说,必须存在继承关系,子类要重写父类的方法,然后通过父类引用指向子类对象,即向上转型。例如,父类Animal有一个eat()方法,子类Dog重写这个方法,然后Animal animal = new Dog(); 这样调用animal.eat()时会执行Dog类的方法。 然后,用户可能需要具体的示例。比如,引用[1]中的代码展示了instanceof的使用,判断对象的运行类型。这里涉及编译类型和运行类型的区别。编译时类型由声明决定,运行时类型由实际赋值对象决定。比如AA aa = new BB(); 编译类型是AA,运行类型是BB。这时候使用instanceof检查时,会根据实际类型判断。 还需要解释多态的表现形式,比如方法重写和重载的区别。重写是多态的一种,而重载是编译时多态。不过通常说的多态是运行时多态,也就是通过方法重写实现的。引用[4]提到多态是数据抽象和继承之后的第三个特征,说明其重要性。 可能还需要提到多态的好处,比如提高代码的可扩展性和可维护性。例如,当新增一个子类时,不需要修改原有的代码,只需扩展即可。引用[2]指出,使用父类对象的地方都可以用子类对象替代,这体现了多态的灵活性。 用户的问题可能还包括多态中的向上转型和向下转型。向上转型是安全的,因为子类是父类的扩展,但向下转型需要强制类型转换,并且可能抛出ClassCastException,所以通常用instanceof检查。 示例部分,可以举一个动物类的例子,父类Animal,子类Dog和Cat重写eat方法,然后用父类引用调用,展示不同的执行结果。这能直观显示多态的动态绑定特性。 最后,可能需要总结多态的条件、实现方式以及应用场景,确保回答结构清晰,用户容易理解。同时,根据系统指令,生成相关问题,比如多态的实现条件、向上转型与向下转型的区别、多态在框架中的应用等。</think>### Java多态概念解析 #### 一、多态的性质 1. **动态绑定**:Java多态的核心是运行时确定方法的具体实现(动态绑定)。例如: ```java Animal animal = new Dog(); animal.sound(); // 实际调用Dog类重写的sound()方法 ``` 这里虽然变量`animal`的编译类型是$Animal$,但运行类型是$Dog$,因此方法调用由运行类型决定[^3][^4]。 2. **向上转型**:子类对象可以赋值给父类引用变量,例如$AA\ aa = new\ BB();$,此时`aa`的编译类型是$AA$,运行类型是$BB$[^1]。 3. **类型检查**:通过`instanceof`运算符可判断对象的实际类型。如: ```java System.out.println(aa instanceof BB); // 输出true(运行类型为BB) System.out.println(o instanceof AA); // 输出false(Object与AA无继承关系) ``` #### 二、多态的实现条件 1. **继承关系**:必须存在父子类继承关系(如$BB\ extends\ AA$)[^3] 2. **方法重写**:子类需重写父类的方法 3. **向上转型**:通过父类引用操作子类对象 #### 三、示例与解释 ```java class Animal { void sound() { System.out.println("动物叫声"); } } class Cat extends Animal { @Override void sound() { System.out.println("喵喵"); } // 重写父类方法 } public class Test { public static void main(String[] args) { Animal a1 = new Cat(); // 向上转型 a1.sound(); // 输出"喵喵"(动态绑定) Animal a2 = new Animal(); a2.sound(); // 输出"动物叫声" } } ``` 该示例中: - $a1.sound()$展示了**多态性**:编译时检查$Animal$类是否有`sound()`方法,运行时执行$Cat$类的实现 - 若删除$Cat$类的`sound()`方法,将调用父类默认实现 #### 四、多态的应用场景 1. **框架设计**:如Spring框架通过父类接口操作不同实现类 2. **集合处理**:使用$List$接口统一操作$ArrayList/LinkedList$ 3. **回调机制**:通过接口实现不同回调逻辑[^2]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值