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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 高盖茨 中级黑马   /  2015-12-6 15:18  /  627 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

多态:(普通类的多态)
        概述:同一对象在不同时刻表现出来的不同状态(形态)。
                比如说:水,常温是液体,高温是气体,低温是固体。

        前提:
                1、要有继承关系。
                2、要有方法重写。
                3、要有父类引用指向子类对象。
                        Animal a = new Cat();

        成员访问角度:
                成员变量:
                        编译看左边(父类),运行看左边(父类)。
                        解释:
                                编译看左边:看的是左边(父类)有没有这个变量,有就编译通过,没有就报错。
                                运行看左边:实际运行,用的还是左边(父类)的成员变量。

                成员方法:
                        非静态方法:(动态绑定)
                                编译看左边(父类),运行看右边(子类)。
                                解释:
                                        编译看左边:看的是左边(父类)有没有这个成员方法,有就编译通过,没有就报错。
                                        运行看右边:实际运行,用的是右边(子类)的成员方法。

                        静态方法:
                                编译看左边(父类),运行看左边(父类)。
                                解释:
                                        编译看左边:看的是左边(父类)有没有这个静态方法,有就编译通过,没有就报错。
                                        运行看左边:实际运行,用的还是左边(父类)的静态方法。
                                理解:
                                        静态成员是属于类的,所以算不上重写。

                总结:
                        只有非静态的方法,是编译看左边,运行看右边。原因是因为:方法有重写。
                        其他(静态方法,成员变量)都是编译看左边(父类),运行看左边(父类)。

                向上和向下转型:
                        double d  = 12;                //隐式类型转换  小给大       
                        int i = (int)d;                //强制类型转换        大转小

                        Fu f = new Zi();        //小给大  向上转型
                        Zi z = (Zi)f;                //大转小  向下转型

                        注意:
                                转型的时候可能会出一个异常:类名转换异常(ClassCastException)
                                原因是:类型不兼容(比如说:要把一个狗转成猫)


                好处和弊端:
                        好处:
                                1、维护性。
                                2、扩展性。
                                3、可以作为方法形参的数据类型,用于接收其任意的子类对象。
                                        public static void method(Animal a) {        //Animal a = new Animal();
                                                                                                                        //Animal a = new Cat();
                                                                                                                        //Animal a = new Dog();
                                                                                                                        //Animal a = new Pig();
                                                //里边放(调用)的一般是所有子类的共性内容。
                                                a.eat();
                                                a.sleep();
                                       
                                        }

                                       
                                        instanceof关键字:
                                                格式:  引用 instanceof 数据类型
                                                解释:  判断前边的引用 是否是 后边的数据类型。

                        弊端:
                                父类引用不能使用子类的特有成员。
               


抽象类的多态:
        抽象类:有抽象方法的类。
        抽象方法:没有方法体的方法就叫抽象方法,用abstract关键字修饰。
                public abstract void show();

        基本特点:
                1、抽象类,抽象方法必须用关键字abstract修饰。
                2、抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类或者接口(接口不是类)。
                3、抽象类不能被实例化。
                        //也就是说,抽象类不能创建该类对象。 Animal(抽象类) a = new Animal();这样写是错误的。
                        抽象类怎么实例化?
                                通过多态,创建其具体的子类对象,来完成实例化。
                4、抽象类的子类:
                        A:要么也是抽象类。
                        B:要么重写抽象类中 所有的抽象方法。

        成员特点:
                成员变量:
                        可以是变量,也可以是常量。
                构造方法:
                        有。
                        抽象类既然不能被实例化,要构造方法有什么用?
                                用于子类对象访问父类数据前,对父类数据进行初始化。
                               
                成员方法:
                        可以是抽象方法,也可以是非抽象方法。
                        抽象方法:强制要求子类必须完成某些事情。
                        非抽象方法:用于被子类继承,提高代码的复用性。

        面试题:
                题目1:一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
                           可以,这么做的目的只有一个,就是不让其他的类来创建该类的对象。

                题目2:abstract关键字不能和哪些关键字共存?
                           private:被private修饰的内容,子类是没有办法继承的,但是抽象方法是要求子类必须重写的,所以他们互相矛盾
                           final:被final修饰的内容,子类是没有办法重写的,但是抽象方法是要求子类必须重写的,所以他们互相矛盾
                           static:被static修饰的内容可以通过类名.的形式调用,但是我们知道抽象方法是没有方法体的,所以及时可以通过类名.的方式去调用,也是没有任何意义的,所以他们不能共存。


接口多态:
        概述:比抽象类更抽象,里边所有的方法都是抽象的。
        基本特点:
                1、接口用关键字interface修饰。
                2、类实现接口用关键字: implements
                3、接口不能实例化。
                        怎么实例化?
                                通过多态,创建其具体的子类对象,来完成实例化。
                4、接口的子类:
                        A:要么是抽象类(接口)。但是意义不大。
                        B:要么是具体类,但是必须重写接口中的所有抽象方法(推荐)。

        成员特点:
                成员变量:
                        只能是常量,因为有默认修饰符:public static final,
                        如果我们不写,系统会默认加上,推荐手动写上。
                构造方法:
                        没有构造方法。

                成员方法:
                        只能是抽象方法,因为有默认修饰符:public abstract
                        如果我们不写,系统会默认加上,推荐手动写上。

                总结:接口中有且只有常量或者抽象方法。

        类与接口的关系:
                类与类:
                        继承。可以单继承,不能多继承,但是可以多层继承。

                类与接口:
                        实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时,实现多个接口。

                接口与接口:
                        继承。可以单继承,也可以多继承。

        抽象类和接口的区别:
                1、成员区别
                2、关系区别
                3、设计理念的区别:
                        抽象类:被继承,体现的是is a的关系,里边定义的是整个继承体系的 共性内容。
                        接口:被实现,体现的是like a的关系,里边定义的是整个继承体系的 扩展内容。
               
       


* A:看下面程序是否有问题,如果没有,说出结果
*
                class Fu {
                        public void show() {
                                System.out.println("fu show");
                        }
                }
       
                class Zi extends Fu {
                        public void show() {
                                System.out.println("zi show");
                        }
       
                        public void method() {
                                System.out.println("zi method");
                        }
                }
       
                class Test1Demo {
                        public static void main(String[] args) {
                                Fu f = new Zi();
                                f.method();
                                f.show();
                        }
                }
* B:看下面程序是否有问题,如果没有,说出结果
*
                class A {
                        public void show() {
                                show2();
                        }
                        public void show2() {
                                System.out.println("我");
                        }
                }
                class B extends A {
                        public void show() {
                                show2();
                        }

                        public void show2() {
                                System.out.println("爱");
                        }
                }
                class C extends B {
                        public void show() {
                                super.show();        //在这里调用了父类的show()方法,这里调用的是show2()
                        }
                        public void show2() {
                                System.out.println("你");
                        }
                }
                public class Test2DuoTai {
                        public static void main(String[] args) {
                                A a = new B();        //多态
                                a.show();        //编译看左,运行看右。                //"爱"
                               
                                B b = new C();        //多态
                                b.show(); //编译看左,运行看右。        "你"
                        }
                }



中午作业:
        1、写代码实现以及理解一下两句话。
                第一个话述:
                        总结:
                                只有非静态的方法,是编译看左边,运行看右边。原因是因为:方法有重写。
                                其他(静态方法,成员变量)都是编译看左边(父类),运行看左边(父类)。

                第二个话述:多态的好处
                        3、可以作为方法形参的数据类型,用于接收其任意的子类对象。
                                        public static void method(Animal a) {       
                                                //里边放(调用)的一般是所有子类的共性内容。
                                                a.eat();
                                                a.sleep();
                                        }




0 个回复

您需要登录后才可以回帖 登录 | 加入黑马