四、面向对象三特征————多态 1、多态:可以理解为事物存在的多种体现形态;举例:人,男人和女人;动物,猫和狗等 2、多态的体现; a) 父类的引用指向了自己的子类对象; b) 父类的引用也可以接收自己的子类对象; 3、多态的前提; a) 必须是类与类之间有关系,要么继承,要么实现; b) 通常,还有一个前提,存在覆盖; 4、多态的好处;多态的出现,大大的提高了程序的扩展性 5、多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员;不可以访问子类中特有的方法。(前期不能使用后期产生的功能,即访问的局限性) 6、多态中的成员变量和成员函数: a) 在多态中,成员函数的特点: i. 在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,没有则编译失败; ii. 在运行时期:参阅对象所属的类中是否有调用的方法。 iii. 简单总结就是:成员函数带多态调用时,编译看左边---运行看右边; b) 在多态中,成员变量的特点; i. 无论编译和运行,都参考左边(引用型变量所属的类)。 c) 在多态中,静态成员函数的特点; i. 无论编译和运行,都参考左边; 7、多态的应用: a) 举例: class 毕姥爷{ void 讲课(){ System.out.println("企业管理"); } void 钓鱼(){ System.out.println("钓鱼"); } } class 毕老师 extends 毕姥爷{ void 讲课(){ System.out.println("JAVA"); } void 看电影(){ System.out.println("看电影"); } } class { public static void main(String[] args) { 毕姥爷 x = new 毕老师(); //毕老师对象被提升为了毕姥爷类型。 // x.讲课(); // x.看电影(); //错误. 毕老师 y = (毕老师)x; //将毕姥爷类型强制转换成毕老师类型。 y.看电影();//在多态中,自始自终都是子类对象在做着类型的变化。 } } B) 如果想用子类对象的特有方法,如何判断对象是哪个具体的子类类型呢? 可以通过一个关键字 instanceof ;//判断对象是否实现了指定的接口或继承了指定的类 格式:<对象 instanceof 类型> ,判断一个对象是否所属于指定的类型。 Student instanceof Person = true;//student继承了person类 8、内部类: a) 内部类访问规则: i. 内部类可以直接访问外部类中的成员,包括私有;之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this ii. 外部类要访问内部类,必须建立内部类的对象; b) 内部类访问格式: ① 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象: 格式————外部类名.内部类名 变量名 = 外部类对象.内部类对象; Outer.Inner in = new Outer().new Inner(); ② 当内部类在成员位置上,就可以被成员修饰符所修饰; 比如:private,将内部类在外部类中进行封装。 static,内部类就具备了静态的特性; 当内部类被static修饰后,只能直接访问外部类的静态成员,出现访问局限。 ③ 在外部其他类中,如何直接访问static内部类的非静态成员呢? new Outer.Inner().function(); ④ 在外部其他类中,如何直接访问static内部类的静态成员呢? Outer.Inner.function(); c) 注意:当内部类定义了静态成员,该内部类必须是静态的; 当外部类中的静态方法,访问内部类时,内部类也必须是静态的; d) 内部类定义在局部时, ① 不可以被成员修饰符修饰; ② 可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。 e) 什么时候定义内部类? 当描述事物时,事物的内部还有事物,该事物用内部类来描述。 因为内部事务在使用外部事物的内容;举例: class Body { private class Xinzang { } public void show() { new Xinzang(); } } 9、匿名内部类: a) 匿名内部类:没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。 b) 匿名内部类格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。 c) 什么时候使用呢? i. 当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。 其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。 d) 举例: //1 new Object(){ void show(){ System.out.println("show run"); } }.show(); //2 Object obj = new Object(){ void show(){ System.out.println("show run"); } }; obj.show(); 1和2的写法正确吗?有区别吗?说出原因。 写法是正确,1和2都是在通过匿名内部类建立一个Object类的子类对象。 区别: 第一个可是编译通过,并运行。 第二个编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了Object类型,而编译时检查Object类中是否有show方法,所以编译失败。 |