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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© osully 金牌黑马   /  2014-3-15 18:55  /  1986 人查看  /  10 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 osully 于 2014-3-15 20:13 编辑

你敢说你懂什么叫多态吗?
敢就不要去打开eclipse或其他软件运行结果 ,直接回复我结果,然后告诉我为什么!

我今天算是迷糊了!!!!复习到什么知识 ,自己写个代码 就把自己绕进去,出不来了!

之前我也是背的:
在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。

在多态中,静态成员函数的特点:
无论编译和运行,都参考做左边。第一题:
  1. class Fu{
  2.         String s = "fu";
  3.         void show(){
  4.                 System.out.println(s);
  5.         }
  6. }

  7. class Zi extends Fu{
  8.         String s = "zi";
  9. }

  10. public class DuoTaiDemo {
  11.         public static void main(String[] args) {
  12.                 Fu f = new Zi();
  13.                 f.show();
  14.                 Zi z = new Zi();
  15.                 z.show();
  16.         }
  17. }
复制代码

第二题:
  1. class Super {
  2.         public int id = 10;

  3.         public void setId(int id) {
  4.                 this.id = id;
  5.         }

  6.         public int getId() {
  7.                 return id;
  8.         }

  9.         public Super() {
  10.                 System.out.println(id);
  11.                 setId(5);
  12.                 System.out.println(getId());
  13.         }
  14. }

  15. class Sub extends Super {
  16.         public int id = 20;

  17.         public void setId(int id) {
  18.                 this.id = id;
  19.         }

  20.         public Sub() {
  21.                 System.out.println(id);
  22.                 setId(15);
  23.                 System.out.println(getId());
  24.         }
  25. }

  26. public class DuoTaiDemo1 {
  27.         public static void main(String[] args) {
  28.                 Super s = new Sub();
  29.         }
  30. }
复制代码




10 个回复

倒序浏览
 面向对象编程有三个特征,即封装、继承和多态。

  封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据。

  继承是为了重用父类代码,同时为实现多态性作准备。那么什么是多态呢?

  方法的重写、重载与动态连接构成多态性。Java之所以引入多态的概念,原因之一是它在类的继承问题上和C++不同,后者允许多继承,这确实给其带来的非常强大的功能,但是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只允许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。

  要理解多态性,首先要知道什么是“向上转型”。

  我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类。我可以通过

  Cat c = new Cat();

  实例化一个Cat的对象,这个不难理解。但当我这样定义时:

  Animal a = new Cat();

  这代表什么意思呢?

  很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特,

  定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。

  所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无可奈何的;

  同时,父类中的一个方法只有在在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用;

  对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。

  看下面这段程序:

  class Father{

  public void func1(){

  func2();

  }

  //这是父类中的func2()方法,因为下面的子类中重写了该方法

  //所以在父类类型的引用中调用时,这个方法将不再有效

  //取而代之的是将调用子类中重写的func2()方法

  public void func2(){

  System.out.println("AAA");

  }

  }

  class Child extends Father{

  //func1(int i)是对func1()方法的一个重载

  //由于在父类中没有定义这个方法,所以它不能被父类类型的引用调用

  //所以在下面的main方法中child.func1(68)是不对的

  public void func1(int i){

  System.out.println("BBB");

  }

  //func2()重写了父类Father中的func2()方法

  //如果父类类型的引用中调用了func2()方法,那么必然是子类中重写的这个方法

  public void func2(){

  System.out.println("CCC");

  }

  }

  public class PolymorphismTest {

  public static void main(String[] args) {

  Father child = new Child();

  child.func1();//打印结果将会是什么?

  }

  }

  上面的程序是个很典型的多态的例子。子类Child继承了父类Father,并重载了父类的func1()方法,重写了父类的func2()方法。重载后的func1(int i)和func1()不再是同一个方法,由于父类中没有func1(int i),那么,父类类型的引用child就不能调用func1(int i)方法。而子类重写了func2()方法,那么父类类型的引用child在调用该方法时将会调用子类中重写的func2()。

  那么该程序将会打印出什么样的结果呢?

  很显然,应该是“CCC”。

  对于多态,可以总结它为:

  一、使用父类类型的引用指向子类的对象;

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

  三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)

  四、变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错。

点评

大哥 别这样复制一堆东西过来啊!!!  发表于 2014-3-15 19:16
回复 使用道具 举报
本帖最后由 黄飞1991 于 2014-3-15 19:46 编辑

Fu f = new Fu();
f.show();
Zi z = new Zi();
z.show();
你这个程序不是多态啊

  • class Fu{
  •         String s = "fu";
  •         void show(){
  •                 System.out.println(this.s);
  •         }
  • }
  • class Zi extends Fu{
  •         String s = "zi";
  • }
  • public class DuoTaiDemo {
  •         public static void main(String[] args) {
  •                 Zi z = new Zi();
  •                 z.show();
  •         }
  • }
结果是:fu


  • class Fu{
  •         String s = "fu";
  • }
  • class Zi extends Fu{
  •         String s = "zi";
  •         void show(){
  •                 System.out.println(this.s);
  •         }
  • }
  • public class DuoTaiDemo {
  •         public static void main(String[] args) {
  •                 Zi z = new Zi();
  •                 z.show();
  •         }
  • }
结果是:zi


注意红色的文字

show()方法在哪个类里,就执行同一个类里的成员变量s。

点评

感谢提醒, 把 Fu f = new Fu(); 改成 Fu f = new Zi();了  发表于 2014-3-15 19:32

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

回复 使用道具 举报
黄飞1991 发表于 2014-3-15 19:30
Fu f = new Fu();
f.show();
Zi z = new Zi();

你这分析的代码  都不是我的源代码啊, 还差一点
再看一下代码吧! 不过this倒是有点意思!
回复 使用道具 举报
  • class Fu{
  •         String s = "fu";
  •         void show(){
  •                 System.out.println(this.s);
  •         }
  • }
  • class Zi extends Fu{
  •         String s = "zi";
  • }
  • public class DuoTaiDemo {
  •         public static void main(String[] args) {
  •                 Fu f = new Zi();
  •                 f.show();
  •                 Zi z = new Zi();
  •                 z.show();
  •         }
  • }
结果是:fu fu
  f.show();的执行和 语句z.show();其实本质上是一样的,
  show()方法运行还是看show()方法在哪个类里定义,就执行同一个类里的成员变量s。



回复 使用道具 举报
黄飞1991 发表于 2014-3-15 20:03
  • class Fu{
  •         String s = "fu";
  •         void show(){

  • 大哥 既然这样的话
    帮个忙看下第二个该如何分析
    回复 使用道具 举报
    李猛 中级黑马 2014-3-15 20:18:52
    7#
    我感觉是因为子类中没有show方法的缘故吧,由于子类继承了父类但没有复写,所以子类会去父类中寻找show方法,因为在父类中的show方法,所以理所应当屏蔽子类的同名变量,就像是全局变量被局部同名变量屏蔽一样
    回复 使用道具 举报
    本帖最后由 zms2100 于 2014-3-15 20:30 编辑

    一句老土简单的话解释 多态: 龙生九子,各有不同,但他们都是龙。
    一、多态的3个必要条件:                  (这三个点缺一不可,其中只有父类拥有的方法才能)
         1.继承(或实现);                 
         2.重写(覆盖);[如果是重载也不行,因为与父类拥有的方法不同]
         3.父类引用指向子类对象         (关键,使用的方式)
    二、按我之前个人的理解: 多态、泛型多少是对Java是强类型语言的弥补;
         在LZ代码的第三个类应该这样表示才是多态的功能:
    public class DuoTaiDemo {
            public static void main(String[] args) {
                    Fu f = new Fu();
                    f.show();
                    Fu z = new Zi();          //父类的引用指向子类对象,当多个不同子类时可通过多态来调用不同子类对象中的共性方法(而方法内容却不同);
                    z.show();                   //这里只能调用父类才有的方法,但是方法等的执行是子类的 。
            }
    }
    你会发现执行结果是相同的,这是因为:         
    多态中:        非静态成员函数是动态绑定;        (哪个类的对象就运行该类的方法)
                    而成员变量以及静态成员函数都是静态绑定;(哪个类的引用就运行该类的变量与静态函数)
             【这个跟看左边和看右边是相同意思,只不过是自己从别的地方学来的总结】
    要结果不一样,重写(复写)下子类 Zi 的show()方法即可;
    class Zi extends Fu{
        String s = "zi";
        void show(){
            System.out.println(s+"+"+this.s+"+"+super.s);        //也可以照抄 Fu 的show()方法;
        }  //第一个s就相当于this.s , 但因为没复写show()方法,所以虚拟机调用父类show()且执行Fu类的成员变量;
    }
    就说这么多了,好久没看Java了,最近在复习,如果有错的地方赶紧提出,O(∩_∩)O~
    多态的使用和泛型(按LZ目前应该还没学到那)都是比较重要的基础,不过在往后视频的高新技术等的反射章节会讲解为什么要用它们(本来想多废话的,不过太长了,另外怕LZ晕了,O(∩_∩)O~)。

    评分

    参与人数 1技术分 +1 收起 理由
    菜小徐 + 1

    查看全部评分

    回复 使用道具 举报
    继承:
    当子类出现和父类一样的函数时,
    子类对象调用该函数;
    运行子类函数的内容
    如同父类函数被覆盖了一样
    这就是函数的另一种特性:重写(覆盖)
    回复 使用道具 举报
    您需要登录后才可以回帖 登录 | 加入黑马