黑马程序员技术交流社区

标题: 求继承和多态图解,为什么这么难 [打印本页]

作者: ZHAOWEI    时间: 2014-5-15 22:38
标题: 求继承和多态图解,为什么这么难
求继承和多态图解,文字的描述我是真的有点理解不了啊,续承懂了一部分,今天学习多态完全混乱了。。。
作者: stream    时间: 2014-5-16 11:23
用一个实例来讲一下多态。。说汽车类有发动引擎和换挡两个方法,自动挡车是对汽车类的继承,并且有自己启动引擎和换挡的方法,手动挡也是。。。那么假设主函数为小明换挡了汽车,这里定义的对象是一个汽车类。。但是实际情况下可以是手动挡或者自动挡,调用的时候呢这个特定的类型就会向上转型为汽车类,只能使用其中汽车类定义了的方法,但是这些方法不是在汽车类中定义的,是在手动挡或者自动挡中定义的方法。。。。。。。。。。。。。。。。。。。。。我自己说得也有点乱了。。。。。你从编译的角度来看这个问题会秒懂的。。。。
作者: 张志民    时间: 2014-5-16 12:15
我说一下多态好了,多态是指父类或者接口的引用型变量指向了堆内存中子类的实体(Fu zi = new Zi())多态的好处:提高了代码的扩展性,前期定义的代码可以使用后期的内容,多态之后会有自动类型提升,会隐藏子类的特有内容和方法,如果要使用子类的特有方法就要向下转型之后才可以使用
作者: 格子、    时间: 2014-5-16 23:05
继承很好理解的啊,就是继承父业嘛,就像你继承了你父亲的家产和技术,这写东西就都是你的了,你还可以自己创业积累家产、学习新的技术啊,对父类没有影响。多态也也是一样,因为有了继承才有了多态!一个类继承了父类,就像你跟你父亲的关系一样,在你身上能找到你的父亲的内容,你父亲的内容也是你的内容之一。this就是指的你的内容,super 就是你父亲的内容啊。
作者: ID1003    时间: 2014-5-17 00:26
其实,继承,简单的来说就是,父类已经实现了的函数,子类就直接拿过来用,但是父类如果只定义了方法却没有定义方法体的话,就需要子类继承过来之后把他实例化,比如说,父类有一个eat();  ,那么子类拿过来之后就要把eat()给完善;就要写出来eat(){.....}这样是子类对父类的成员方法继承,还有需要注意的是子类默认调用父类的无参构造方法,如果父类没有无参构造,那么就必须要标明有参构造函数。
作者: ID1003    时间: 2014-5-17 00:29
多态,首先说子类,子类通过继承得到了父类中的函数(方法),而他自己本身还可以定义更多自己的方法,这些子类自己的方法,父类是没有的。而子类中通过继承得来的方法呢,父类可以直接通过子类的实例化对象来使用,就比如Fu f=new Zi();说的直白一点就是创建一个子类对象,然后有一个父类对象来从子类这里使用他俩共有的一些东西。
作者: 张百振    时间: 2014-5-17 01:00

12-多态的概述
    | 某一类事物的多种存在形态
    | 程序中的体现:
        | 父类或者接口的引用指向或者接收自己的子类对象
        Person p = new Girl();   
    /*
    final关键字
        最终的

    final可以修饰类,方法,变量。
        final修饰的方法不可以被覆盖。
        final修饰的变量是一个常量。只能被赋值一次。
            常量来说的修饰符 一般来说: public static final double PI = 3.14;

        final修饰的类不可以被继承。
*/

//final class Fu {//错误: 无法从最终Fu进行继承

class Fu {
    //public final void show(){//错误: Zi中的show()无法覆盖Fu中的show()   被覆盖的方法为final
    public final void show(){
        System.out.println("一夫一妻制");
    }
}

class Zi extends Fu{
    final int num;
    /*
        扩展: 如果final修饰的变量没有默认值,可以在构造方法中给num 赋值一次
    */
    public Zi(){
        num = 20;
    }

    public void show(){
        System.out.println("一夫多妻制");
    }
}

class FinalDemo {
    public static void main(String[] args)    {
        Zi z = new Zi();
        z.show();

        //z.num = 30;//错误: 无法为最终变量num分配值
        //System.out.println(z.num);
    }
}

   
   
13-多态的成员特点(成员变量)
14-多态的成员特点(成员变量图解)
    | 编译看左边的父类
    | 执行看左边的父类
    | 只有创建对象, 才能调用构造方法
    /*
    多态的成员
        成员变量
            编译看左边的父类,执行看左边的父类
*/
class Fu {
    int num = 10;
}

class Zi extends Fu {
    int num = 20;
    int num2 = 30;
}

class DuoTaiDemo2 {
    public static void main(String[] args)    {
        
        //Zi z = new Zi();
        //System.out.println(z.num);

        //Fu f = new Fu();
        //System.out.println(f.num);

        //多态的方式
        Fu f2 = new Zi();
        System.out.println(f2.num);// 错误: 找不到符号  位置: 类型为Fu的变量 f2
        //System.out.println(f2.num2);
    }
}


15-多态的成员特点(成员方法)
    | 编译看左边的父类
    | 执行看右边的子类
    /*
    多态的成员
        成员方法:
            编译看左边的父类
            执行看右边的子类
*/
class Fu {   
    public void show(){
        System.out.println("Fu show");
    }
}

class Zi extends Fu {   
    public void show(){
        System.out.println("Zi show");
    }
}

class DuoTaiDemo3 {
    public static void main(String[] args)    {
        //Fu f = new Fu();
        //f.show();

        //Zi z = new Zi();
        //z.show();

        //多态的方式
        Fu f2 = new Zi();
        f2.show();
    }
}


16-多态的成员特点(静态方法)
    | 编译看左边的父类
    | 执行看左边的父类
    | 静态是随着类的加载而存在,对象还没有创建,所以调用的时候,使用的Fu中的静态方法
    /*
    多态的特点
        静态方法
        编辑看左边的父类
        执行看左边的父类

    关于多态的特点的总结:

        成员方法执行看右边,其他都看左边.
*/
class Fu{
    public static void show(){
        System.out.println("Fu show");
    }
}

class Zi extends Fu {
    public static void show(){
        System.out.println("Zi show");
    }
}

class DuoTaiDemo4 {
    public static void main(String[] args)    {
        //Fu f = new Fu();
        //f.show();
        //Fu.show();

        //Zi z = new Zi();
        //z.show();
        //Zi.show();

        //多态的方式
        Fu f2 = new Zi();
        f2.show();
        //Fu.show();
        /*
            在调用静态show方法的时候,对象可能还没有创建出来,
            所以,当前的静态方法可以通过类名.方法名来调用
            这个show方法  Fu.show();
            当前的f2.show();中的f2 它Fu类型,它可以通过Fu.show()来调用,效果是等价的


        */

    }
}

   
17-多态的好处
    | 提高了程序的扩展性
    /*
    好处和作用:
        多态的存在提高了程序的扩展性和后期可维护性
        
        后期可维护性(父类Person 来完成的)

    多态的弊端:
        父类不能访问子类特有方法

    Person
        | Boy
        | Girl
        | Other

*/
class Person {
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
}

class Girl extends Person {
    public void eat(){
        System.out.println("女生 吃饭少");
    }
    public void sleep(){
        System.out.println("女生 睡觉早");
    }
    public void goShopping(){
        System.out.println("带着男朋友逛商场");
    }
}

class Boy extends Person{
    public void eat(){
        System.out.println("男生 吃饭多");
    }
    public void sleep(){
        System.out.println("男生 睡觉晚");
    }
}

class Other extends Person{
    public void eat(){
        System.out.println("other 吃饭");
    }
    public void sleep(){
        System.out.println("other 睡觉");
    }
}


class DuoTaiDemo5 {
    public static void main(String[] args)    {
        /*
        Girl g = new Girl();
        g.eat();
        g.sleep();

        Girl g2 = new Girl();
        g2.eat();
        g2.sleep();
        */
        Girl g3 = new Girl();
        girlMethod(g3);

        Boy b = new Boy();
        boyMethod(b);

        Other o = new Other();
        otherMethod(o);

        //------------------------
        //多态的方式
        Person g4 = new Girl();
        personMethod(g4);

        Person b2 = new Boy();
        personMethod(b2);

        Person o2 = new Other();
        personMethod(o2);

        //------------------------
        //多态的弊端
        Girl g5 = new Girl();
        g5.goShopping();

        Person g6 = new Girl();
        g6.goShopping();


    }

    //多态方式的方法
    public static void personMethod( Person p ){
        p.eat();
        p.sleep();
    }

    //其他人方法
    public static void otherMethod( Other o ){
        o.eat();
        o.sleep();
    }

    //男生方法
    public static void boyMethod( Boy b ){
        b.eat();
        b.sleep();
    }

    //女生方法
    public static void girlMethod( Girl g ){
        g.eat();
        g.sleep();
    }
}


18-多态的弊端
    | 父类不能访问子类特有方法
   
19-多态的案例(向上转型、向下转型)
    | 向上转型: 提高了程序的扩展性  
        Person g = new Girl();
    | 向下转型:为了使用子类的特有方法
        Girl girl = (Girl)g;
    /*
    多态的案例
        向上转型: 提高了程序的扩展性
        
        Person p = new UltraMan();
        子类 转型 父类使用
        小   -->    大        隐式转换  自动类型提升
        
        //--------------------------------------------------

        向下转型: 为了使用子类的特有方法

        UltraMan ultra = (UltraMan)p;
        父类 强转 子类使用
        大   --->   小        强制转换

    案例: 奥特曼打小怪兽

    人: name , 吃饭eat()
    奥特曼: name , 吃饭eat() ,打架fight()
*/
class Person {
    String name = "成龙";
    public void eat(){
        System.out.println("成龙 吃饭");
    }
}

class UltraMan extends Person{
    //特有方法
    public void fight(){
        System.out.println("奥特曼打小怪兽");
    }
}

class DuoTaiDemo6 {
    public static void main(String[] args)    {
        Person p = new UltraMan();//向上转型
        System.out.println(p.name);
        p.eat();

        UltraMan ultra = (UltraMan)p;//向下转型
        ultra.fight();

    }
}


作者: 张百振    时间: 2014-5-17 01:04
        这是我前段时间学习面向对象的课堂总结,正好是继承和多态,有好多代码体现,希望可以帮到你
     刚刚自己画的内存图和继承图解传不了,如果你还不明白的话,私下问我,我给你发图解


01-继承的概述
    | 例子: 爹的票子、车子、房子最终都是我的
    |        我的姓 是由 爹而来的
    | 继承的概述.
    /*
    继承的概述
    多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,
    那么多个类无需再定义这些属性和行为,只要继承那个类即可。
    多个类可以称为子类,单独这个类称为父类或者超类

    继承的出现提高了代码的复用性。
    继承的出现让类与类之间产生了关系,提供了多态的前提。

    定义继承需要注意:
        不要仅为了获取其他类中某个功能而去继承
        类与类之间要有所属( " is a " )关系,xx1是xx2的一种。


    案例: 爹的房子、票子、车子 最终统统是我的
           爹姓李,我跟着爹的姓, 这也是继承的体现

    好处: 爹的内容 儿子可以用
*/
class Teacher {
    public void eat (){
        System.out.println("吃饭");
    }
}

class Student {
    public void eat(){
        System.out.println("吃饭");
    }
}

/*
    发现多个类中 有一样的内容,将一样的内容 抽取出来到一个类的中的,
    原有的类就不需要在定义这些内容了.
*/
class Person {
    public void eat() {
        System.out.println("吃饭");
    }
}

/*
    当前这个类 定义好了, 但是怎么和其他类进行相互访问呢?
    可以让类与类之间产生关系, 继承关系

    java中,可以通过关键字 extends 来实现继承关系
    格式:
        class 儿子类 extends 父亲类 {......}
*/
class Teacher extends Person { }
class Student extends Person { }
   
03-继承的特点(子类可以访问父类非私有的内容)
    | 子类可以访问父类非私有的内容
    | 例子:你和媳妇开心,你儿子不能和你媳妇开心
    /*
    继承的特点:

        子类可以直接访问父类中的非私有的属性和行为。

    案例: 你和你媳妇在开心(开心的方法 必须要私有), 你儿子能继承和你媳妇开心的方法吗? 不能
*/
class Fu {
    int num = 10;
    private int num2 = 20;

    public void show(){
        System.out.println("哈哈");
    }
}

class Zi extends Fu {
}

class ExtendsDemo {
    public static void main(String[] args)    {
        
        Zi z = new Zi();
        System.out.println(z.num);
        z.show();
        
        System.out.println(z.num2);// 错误: num2可以在Fu中访问private
    }
}

   
04-继承的特点(Java只支持单继承,不支持多继承)
    | Java只支持单继承,不支持多继承
    | 亲爹只有一个,不能多个
    /*
    多态的成员
        成员变量
            编译看左边的父类,执行看左边的父类
*/
class Fu {
    int num = 10;
}

class Zi extends Fu {
    int num = 20;
    int num2 = 30;
}

class DuoTaiDemo2 {
    public static void main(String[] args)    {
        
        //Zi z = new Zi();
        //System.out.println(z.num);

        //Fu f = new Fu();
        //System.out.println(f.num);

        //多态的方式
        Fu f2 = new Zi();
        System.out.println(f2.num);// 错误: 找不到符号  位置: 类型为Fu的变量 f2
        //System.out.println(f2.num2);
    }
}

   
05-继承的特点(Java支持多层(重)继承)
    | Java支持多层(重)继承
    | 姓的案例  
    /*
    继承的特点:
        Java支持多层(重)继承(继承体系)

*/
//class Yy extends Object {  //Object任何类都有一个祖宗类,叫 Object类
class Yy {
    String name = "Li";
}

class Fu extends Yy {
    String firstName = "李";
}

class Zi extends Fu {

}


class ExtendsDemo3 {
    public static void main(String[] args)    {
        Zi z = new Zi();
        System.out.println(z.firstName);
        System.out.println(z.name);
    }
}


06-继承的代码体现(成员变量)
    | 访问父类成员变量: super.成员变量
    | 访问子类成员变量: this.成员变量
    /*
    继承的代码体现
        成员变量:
        

    如果局部变量与成员变量重复,使用 this 关键字来区别
    格式:this.成员变量

    如果子类与父类中的成员重复时,使用 super 关键字来 区别
    格式:super.成员变量

    this代表本类对象的引用
    super代表父类的引用

    变量的使用原则:就近原则
        局部位置有,使用局部的变量
        成员位置有,使用成员变量
        父类位置有,使用父类的成员变量
        如果父类位置也没有,报错
*/
class Fu {
    int num = 10;
    int num2 = 40;
}

class Zi extends Fu{
    int num = 20;
    public void show(){
        int num = 30;

        System.out.println(num);
        System.out.println(this.num);
        System.out.println(super.num);

        System.out.println(num2);
    }
}

作者: 帽子    时间: 2014-5-17 04:15
多态体现;Animal a = new cat();
父类指向子类,
作者: 927233671    时间: 2014-5-17 22:57
本帖最后由 927233671 于 2014-5-17 23:04 编辑
  1. class Student
  2. {
  3.         private int age;//自定义一个成员变量
  4.         Student(int age)//父类的含有一个参数的构造函数;
  5.         {
  6.                 this.age=age;
  7.         }
  8.         public void speak()//父类的方法
  9.         {
  10.                 System.out.println("我的年龄是 "+age);
  11.         }


  12. }
  13. class Girl extends Student//Girl类继承父类
  14. {
  15.         Girl(int age)//子类的构造函数
  16.         {
  17.                 super(age);//子类直接调用父类构造函数
  18.         }
  19.     public void ku()//子类自己特有的方法
  20.         {
  21.                 System.out.println("我是女生我爱哭");
  22.         }

  23. }


  24. class Demo
  25. {
  26.         public static void main(String[] args)
  27.         {
  28.                 Student g=new Girl(20);//这就是多态的体现,父类引用指向子类对象,写成Girl g=new Girl(20)也一样;
  29.                 g.speak();//g.ku()是不对的,因为这时候g是父类的引用,不可以调用子类的特有方法。
  30.                 Girl s=(Girl)g;//需要强转; 如果父类对象的引用指向的实际是一个子类的对象,那么父类对象的引用可以强制转化成子类对象的引用
  31.                 s.ku();
  32.                
  33.         }
  34. }
复制代码

我举得例子纯手打,希望看我这个能让你搞懂,再结合毕向东老师视频看看
作者: 元亨利贞    时间: 2014-5-17 23:46
http://www.cnblogs.com/520zzh/archive/2010/01/12/1645407.html

作者: 小小6456    时间: 2014-5-18 10:03
学习一下啊。。。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2