A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 杨冉 中级黑马   /  2013-4-9 00:00  /  2281 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

到现在一直不知道JAVA中我们为什么要利用多态性,多态究竟为我们带来什么好处呢?
老师说可以降低耦合,提高扩展性,但谁能举个合适的例子说明到底哪里用到了多态,同时又是如何降低了耦合提高了拓展性呢?
琢磨一晚上了,看了些文章但还是一头雾水。。。

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

13 个回复

倒序浏览
一个类Cat 猫
有一个方法 void eat(Cat c){}
当出现另外类 Dog 时,你还要在写个void eat (Dog d){}  方法

如果你将 void eat(Animal a){}      //animal 动物
每个动物都继承Animal 类
那么就写一个eat方法可以了
  Animal 可以接收自己子类的对象

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
可以这么说吧,Java没有多态,后面的就什么也干不了。简单一句话:所有的子类对象都可以当父类对象来用,一个父类型的引用可能指向的是一个子类对象,接口类似。概念那些这里就不说了,主要是理解。

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
多态性:在程序中的体现。
        就是:父类或者接口的引用指向自己的子类对象。
       

好处:提高了代码的扩展性。

弊端:前期建立父类的引用虽然可以接收后期所有该类的子类对象。
          但是只能使用父类中的功能呢,不能使用子类中的特有功能,
          因为前期的程序无法知道后期的子类的特有内容的。
          但是前期的程序可以使用子类覆盖了父类的方法的内容。

前提:
        1,必须存在着继承关系。
        2,通常要有覆盖操作。
  1. abstract class Animal
  2. {
  3.         abstract void eat();
  4. }

  5. class Dog extends Animal
  6. {
  7.         public void eat()
  8.         {
  9.                 System.out.println("啃骨头");
  10.         }
  11.         public void lookHome()
  12.         {
  13.                 System.out.println("看家");
  14.         }
  15. }


  16. class DuoTaiDemo
  17. {
  18.         public static void main(String[] args)
  19.         {

  20.                
  21.        
  22.                 Animal a = new Dog();//子类对象的类型提升。向上转型。
  23.                 a.eat();
  24.                 /*
  25.                 好处:提高了扩展性,局限:只能使用父类中的方法。
  26.                 这种提升可以限制对子类对象的操作。

  27.                 */

  28.                 Dog d = (Dog)a;//向下转型。 转成子类型。
  29.                 d.eat();
  30.                 d.lookHome();
  31.                 /*
  32.                 可以使用子类的特有方法。
  33.                 弊端,如果类型转换错误,会出现运行异常。
  34.                 */
  35.                
  36.         }

  37.                
  38.         }
复制代码

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
概念:事物存在的多种体现形态,你已经看了些文章,有些雾水,这时,建议你再看两遍毕老师的视频,毕老师讲的很透彻,多敲点有关多态的代码,边敲边理解,跟着毕老师的讲解敲个3、5遍就理解了
另外:耦合是指两个实体相互依赖于对方的一个量度 降低了耦合度,就是说降低了相互依赖程度.
回复 使用道具 举报
一句话,父类或者接口可以引用子类对象和实现该接口的类对象
回复 使用道具 举报
当接口出现的时候,多态就开始渐渐明朗了。
当你的项目拥有了一种功能,那么只要使用功能就可以了。
父类可以当作子类来使用,这样的话可以写出通用性比较好的代码,使用起来更为宽松和方便。
一句话吧:子类重写父类的代码,就是使用父类的功能,创造具有子类特性的代码出来。

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
多态一类事物的多种状态。举个例子:public boolean equals (Object obj){...};Oject类是java中所有类的基类。所以我们可以传任意类型的参数,java在定义这个方法的时候不知道,程序员要传入什么类型的参数,所以就指定类型为所有类型的父类,父类引用指向子类对象,这样就提高了代码的扩展性。没有继承就没有多态。多态用的最多的就是这种参数传递。我们在使用参数的时候在将类型强转过来。耦合性说的是,我们想对原有程序做修改的时候,就可以不用修改原程序,直接用另一个子类对象就行了。如:Animal cat = new Cat(); cat.eat(); cat.sleep();当我们想要把猫变成狗的时候,就直接Animal cat = new Dog()即可。这样就降低了程序之间的关系。

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
多态体现在父类和接口及它们的导出类之间。当调用父类及接口中的方法时,JVM自动判断应调用那个导出类的方法。

假如有这样一个方法: Map getMap(){ new HashMap();},
可能以后对这个Map有同步要求,就可以把方法内部实现改为 new Hashtable(); 或 new ConcurrentHashMap(); 而调用这个方法的地方不需要改动。

基于接口编程,就是应用多态的体现。

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
多态是面向对象的基本特征之一,也是软件工程的重要思想。
多态,通俗地讲就是一个事务在不同情况下展现不同的形态,其实,函数重载就是一种多态,称为静态多态。而我们说的多态大多是动态多态。
动态多态的理论基础是:父类引用可以指向子类对象,也就是可以这样定义一个对象:父类名  对象名  =  new  子类名();
这样在该对象调用方法时,会优先调用子类的方法,当子类中没有某个方法时再调用父类的方法。
这点可以进行延伸:
1.函数传入的形参可以是弗雷类型,而实际传入的可以是子类对象
如:
  1. public static void fun(父类名   对象){
  2.                 父类.show();
  3.         }
  4.         public static void main(String[] a){
  5.                 fun(new 子类名());
  6.         }
复制代码
2.函数的返回类型是父类类型,实际返回的可以是子类对象。
如:
  1. public static 父类 fun(){
  2.                 return new 子类名();
  3.         }
  4.         public static void main(String[] a){
  5.                 父类名  对象名 = fun();
  6.                 对象名.show();
  7.         }
复制代码

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。多态有两种表现形式:重载和覆盖首先说重载(overload),是发生在同一类中。与什么父类子类、继承毫无关系。      标识一个函数除了函数名外,还有函数的参数(个数和类型)。也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同。      他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性,仅此而已!        再说覆盖(override),是发生在子类中!也就是说必须有继承的情况下才有覆盖发生。    我们知道继承一个类,也就有了父类了全部方法,如果你感到哪个方法不爽,功能要变,那就把那个函数在子类中重新实现一遍。    这样再调用这个方法的时候,就是执行子类中的过程了。父类中的函数就被覆盖了。(当然,覆盖的时候函数名和参数要和父类中完全一样,不然你的方法对父类中的方法就不起任何作用,因为两者是两个函数,毫不关系)

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
引用张孝祥老师Java就业培训教材p143页的一个讲解: 有一个“叫某人来吃饭”的函数,在函数内部,是这样写的:void 叫某人来吃饭(人 p){ p.吃饭(); }  当来的是一个中国人的时候,我们看到的是用筷子在吃饭。但是如果叫过来的是一个美国人,我们看到的就是用刀叉在吃饭。同样的一段代码(指“叫某人来吃饭”这个函数),却可能显示出不同的结果,这个就是面向对象的多态性。

个人感觉这个例子比较直观。

评分

参与人数 1技术分 +1 收起 理由
陈丽莉 + 1

查看全部评分

回复 使用道具 举报
父类的引用指向子类实例,在运行时才确定是哪个方法,即子类实例对象的方法。
回复 使用道具 举报
问题虽然已经解决,但我觉得,自己总结了,还是拿来分享下,希望能更好的帮助你理解
  1. class Father
  2. {
  3.         String father = "father";
  4.         public void show(){
  5.                         System.out.println("Father is show()");
  6.         }
  7.         public void show1(){
  8.                         System.out.println("Father  show1111()");
  9.         }
  10. }
  11. class Son extends Father
  12. {
  13.         String father = "son";
  14.         String son = "子类特有的";
  15.         //重写了父类方法
  16.         public void show(){
  17.                         System.out.println("Son is show()");
  18.         }
  19.         //重载父类的方法,但对于父类,是一个新增加的功能
  20.         public void show(int i){
  21.                 System.out.println("Son is show() again");
  22.         }
  23. }
  24. class ExtendsDemo
  25. {
  26.         public static void main(String []args){
  27.                        
  28.                 Father f = new Father();//
  29.                 Father s = new Son();//创建一个父类引用指向子类对象
  30.                 Son son = new Son();//
  31.                 f.show();//父亲访问自己的方法
  32.                 s.show();//由于父类引用指向了子类对象,子类又对父类的show()方法进行了重写,故访问子类的方法
  33.                 //s.show(1);//show(int i)由于是子类新增加的功能,父类并不知道,所以不能调用,会编译不过
  34.                 s.show1();//子类并没有重写父类show1()方法,故会去调用父类的方法show1()
  35.                 System.out.println("Father f :"+f.father);//调用父类属性
  36.                 System.out.println("Father s :"+s.father);//调用父类属性
  37.                 System.out.println("Father s:"+f.son);//为子类Son新增加的属性,父类不能调用,编译不过
  38.         }
  39. }
  40. /*运行结果:
  41.                 Father is show()
  42.                 Son is show()
  43.                 Father  show1111()
  44.                 Father f :father
  45.                 Father s :father
  46. */
  47.        
  48. /*
  49.         多态的三个必要条件:
  50.                  1.继承   2.重写   3.父类引用指向子类对象。
  51.         总结:
  52.        
  53.                 一、使用父类类型的引用指向子类的对象;

  54.                 二、该引用只能调用父类中已经定义的方法和变量;

  55.                 三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)
  56.                                 动态绑定是指”在执行期间(而非编译期间)“判断所引用对象的实际类型,根据实际的类型调用其相应的方法。

  57.                 四、变量不会被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在调用时,还是会调用父类的变量
  58.                
  59. */
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马