黑马程序员技术交流社区
标题:
对于多态到底该怎么理解?
[打印本页]
作者:
杨冉
时间:
2013-4-9 00:00
标题:
对于多态到底该怎么理解?
到现在一直不知道JAVA中我们为什么要利用多态性,多态究竟为我们带来什么好处呢?
老师说可以降低耦合,提高扩展性,但谁能举个合适的例子说明到底哪里用到了多态,同时又是如何降低了耦合提高了拓展性呢?
琢磨一晚上了,看了些文章但还是一头雾水。。。
作者:
余善航
时间:
2013-4-9 00:19
一个类Cat 猫
有一个方法 void eat(Cat c){}
当出现另外类 Dog 时,你还要在写个void eat (Dog d){} 方法
如果你将 void eat(Animal a){} //animal 动物
每个动物都继承Animal 类
那么就写一个eat方法可以了
Animal 可以接收自己子类的对象
作者:
柳 德 彬
时间:
2013-4-9 00:24
可以这么说吧,Java没有多态,后面的就什么也干不了。简单一句话:所有的子类对象都可以当父类对象来用,一个父类型的引用可能指向的是一个子类对象,接口类似。概念那些这里就不说了,主要是理解。
作者:
李芳池
时间:
2013-4-9 00:31
多态性:在程序中的体现。
就是:父类或者接口的引用指向自己的子类对象。
好处:提高了代码的扩展性。
弊端:前期建立父类的引用虽然可以接收后期所有该类的子类对象。
但是只能使用父类中的功能呢,不能使用子类中的特有功能,
因为前期的程序无法知道后期的子类的特有内容的。
但是前期的程序可以使用子类覆盖了父类的方法的内容。
前提:
1,必须存在着继承关系。
2,通常要有覆盖操作。
abstract class Animal
{
abstract void eat();
}
class Dog extends Animal
{
public void eat()
{
System.out.println("啃骨头");
}
public void lookHome()
{
System.out.println("看家");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Animal a = new Dog();//子类对象的类型提升。向上转型。
a.eat();
/*
好处:提高了扩展性,局限:只能使用父类中的方法。
这种提升可以限制对子类对象的操作。
*/
Dog d = (Dog)a;//向下转型。 转成子类型。
d.eat();
d.lookHome();
/*
可以使用子类的特有方法。
弊端,如果类型转换错误,会出现运行异常。
*/
}
}
复制代码
作者:
董霁辉
时间:
2013-4-9 00:37
概念:事物存在的多种体现形态,你已经看了些文章,有些雾水,这时
,建议你再看两遍毕老师的视频,毕老师讲的很透彻,多敲点有关多态的代码,边敲边理解,
跟着毕老师的讲解敲个3、5遍就理解了
另外:耦合是指两个实体相互依赖于对方的一个量度 降低了耦合度,就是说降低了相互依赖程度.
作者:
王大斌
时间:
2013-4-9 01:01
一句话,父类或者接口可以引用子类对象和实现该接口的类对象
作者:
黄辉
时间:
2013-4-9 03:55
当接口出现的时候,多态就开始渐渐明朗了。
当你的项目拥有了一种功能,那么只要使用功能就可以了。
父类可以当作子类来使用,这样的话可以写出通用性比较好的代码,使用起来更为宽松和方便。
一句话吧:子类重写父类的代码,就是使用父类的功能,创造具有子类特性的代码出来。
作者:
黑马李杰
时间:
2013-4-9 07:10
多态一类事物的多种状态。举个例子:public boolean equals (Object obj){...};Oject类是java中所有类的基类。所以我们可以传任意类型的参数,java在定义这个方法的时候不知道,程序员要传入什么类型的参数,所以就指定类型为所有类型的父类,父类引用指向子类对象,这样就提高了代码的扩展性。没有继承就没有多态。多态用的最多的就是这种参数传递。我们在使用参数的时候在将类型强转过来。耦合性说的是,我们想对原有程序做修改的时候,就可以不用修改原程序,直接用另一个子类对象就行了。如:Animal cat = new Cat(); cat.eat(); cat.sleep();当我们想要把猫变成狗的时候,就直接Animal cat = new Dog()即可。这样就降低了程序之间的关系。
作者:
何衍其
时间:
2013-4-9 07:20
多态体现在父类和接口及它们的导出类之间。当调用父类及接口中的方法时,JVM自动判断应调用那个导出类的方法。
假如有这样一个方法: Map getMap(){ new HashMap();},
可能以后对这个Map有同步要求,就可以把方法内部实现改为 new Hashtable(); 或 new ConcurrentHashMap(); 而调用这个方法的地方不需要改动。
基于接口编程,就是应用多态的体现。
作者:
王怀亮
时间:
2013-4-9 13:29
多态是面向对象的基本特征之一,也是软件工程的重要思想。
多态,通俗地讲就是一个事务在不同情况下展现不同的形态,其实,函数重载就是一种多态,称为静态多态。而我们说的多态大多是动态多态。
动态多态的理论基础是:父类引用可以指向子类对象,也就是可以这样定义一个对象:父类名 对象名 = new 子类名();
这样在该对象调用方法时,会优先调用子类的方法,当子类中没有某个方法时再调用父类的方法。
这点可以进行延伸:
1.函数传入的形参可以是弗雷类型,而实际传入的可以是子类对象
如:
public static void fun(父类名 对象){
父类.show();
}
public static void main(String[] a){
fun(new 子类名());
}
复制代码
2.函数的返回类型是父类类型,实际返回的可以是子类对象。
如:
public static 父类 fun(){
return new 子类名();
}
public static void main(String[] a){
父类名 对象名 = fun();
对象名.show();
}
复制代码
作者:
杨武林
时间:
2013-4-9 13:34
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。多态有两种表现形式:重载和覆盖首先说重载(overload),是发生在同一类中。与什么父类子类、继承毫无关系。 标识一个函数除了函数名外,还有函数的参数(个数和类型)。也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同。 他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性,仅此而已! 再说覆盖(override),是发生在子类中!也就是说必须有继承的情况下才有覆盖发生。 我们知道继承一个类,也就有了父类了全部方法,如果你感到哪个方法不爽,功能要变,那就把那个函数在子类中重新实现一遍。 这样再调用这个方法的时候,就是执行子类中的过程了。父类中的函数就被覆盖了。(当然,覆盖的时候函数名和参数要和父类中完全一样,不然你的方法对父类中的方法就不起任何作用,因为两者是两个函数,毫不关系)
作者:
HM许涛
时间:
2013-4-9 13:49
引用张孝祥老师Java就业培训教材p143页的一个讲解: 有一个“叫某人来吃饭”的函数,在函数内部,是这样写的:void 叫某人来吃饭(人 p){ p.吃饭(); } 当来的是一个中国人的时候,我们看到的是用筷子在吃饭。但是如果叫过来的是一个美国人,我们看到的就是用刀叉在吃饭。同样的一段代码(指“叫某人来吃饭”这个函数),却可能显示出不同的结果,这个就是面向对象的多态性。
个人感觉这个例子比较直观。
作者:
HM谢文辉
时间:
2013-4-9 13:53
父类的引用指向子类实例,在运行时才确定是哪个方法,即子类实例对象的方法。
作者:
hacket
时间:
2013-4-9 16:52
问题虽然已经解决,但我觉得,自己总结了,还是拿来分享下,希望能更好的帮助你理解
class Father
{
String father = "father";
public void show(){
System.out.println("Father is show()");
}
public void show1(){
System.out.println("Father show1111()");
}
}
class Son extends Father
{
String father = "son";
String son = "子类特有的";
//重写了父类方法
public void show(){
System.out.println("Son is show()");
}
//重载父类的方法,但对于父类,是一个新增加的功能
public void show(int i){
System.out.println("Son is show() again");
}
}
class ExtendsDemo
{
public static void main(String []args){
Father f = new Father();//
Father s = new Son();//创建一个父类引用指向子类对象
Son son = new Son();//
f.show();//父亲访问自己的方法
s.show();//由于父类引用指向了子类对象,子类又对父类的show()方法进行了重写,故访问子类的方法
//s.show(1);//show(int i)由于是子类新增加的功能,父类并不知道,所以不能调用,会编译不过
s.show1();//子类并没有重写父类show1()方法,故会去调用父类的方法show1()
System.out.println("Father f :"+f.father);//调用父类属性
System.out.println("Father s :"+s.father);//调用父类属性
System.out.println("Father s:"+f.son);//为子类Son新增加的属性,父类不能调用,编译不过
}
}
/*运行结果:
Father is show()
Son is show()
Father show1111()
Father f :father
Father s :father
*/
/*
多态的三个必要条件:
1.继承 2.重写 3.父类引用指向子类对象。
总结:
一、使用父类类型的引用指向子类的对象;
二、该引用只能调用父类中已经定义的方法和变量;
三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)
动态绑定是指”在执行期间(而非编译期间)“判断所引用对象的实际类型,根据实际的类型调用其相应的方法。
四、变量不会被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在调用时,还是会调用父类的变量
*/
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2