目录
注意:在进行对象向下转型前,必须先进行对象向上转型,否则将出现对象转换异常
设计一个方法,要求此方法可以接收父类的任意子类对象,并调用方法
一 、对象转型
面对对象有三大特征:封装性、继承性、多态性。而多态性在面向对象中是一个最重要的概念,在Java中面向对象主要有以下两种主要体现:
(1)方法的重载与覆写
(2)对象的多态性
对象的多态性主要分为以下两种类型:
(1)向上转型:子类对象 → 父类对象
(2)向下转型:父类对象 → 子类对象
【对象转型格式】
对象向上转型:父类 父类对象 = 子类实例
对象向下转型:子类 子类对象 = (子类)父类实例
1 、对象的向上转型
class A{
public void fun1(){
System.out.println("A --> public void fun1(){}");
}
public void fun2(){
this.fun1();
}
}
class B extends A{
public void fun1(){ //覆写父类A的fun1方法
System.out.println("B --> public void fun1(){}");
}
public void fun3(){
System.out.println("B --> public void fun3(){}");
}
}
public class PolDemo01 {
public static void main(String[] args) {
B b = new B(); //实例化子类对象
A a = b ; //对象向上转型:父类 父类对象 = 子类实例
a.fun1(); //此方法被子类覆写过
}
}
程序运行结果:
从程序运行结果发现,发生向上转型后,父类对象实际上调用的是被子类覆写过的方法,如果子类没有覆写父类的方法,则父类对象调用自己的方法,同时要注意:此时父类对象a是无法调用到B类中的fun3()方法的,因为此方法只在子类中定义,而没有在父类中定义。
也就是说,以前对象只能调用自己类中的方法,发生向上转型关系后,父类对象不仅可以调用自己类中的方法,还可以调用子类中覆写父类的方法
而向下转型之后,子类对象可以调用子类、父类中的所有方法
2 、对象的向下转型
class A{
public void fun1(){
System.out.println("A --> public void fun1(){}");
}
public void fun2(){
this.fun1();
}
}
class B extends A{
public void fun1(){ //覆写父类A的fun1()方法
System.out.println("B --> public void fun1(){}");
}
public void fun3(){
System.out.println("B --> public void fun3(){}");
}
}
public class PolDemo01 {
public static void main(String[] args) {
A a = new B(); //发生向上转型
B b = (B)a; //发生向下转型
b.fun1();
b.fun2();
b.fun3();
}
}
程序运行结果:
如果子类B没有覆写父类A的方法,则子类对象b将调用父类A中的fun1()方法,代码如下:
class A{
public void fun1(){
System.out.println("A --> public void fun1(){}");
}
public void fun2(){
this.fun1();
}
}
class B extends A{
public void fun3(){
System.out.println("B --> public void fun3(){}");
}
}
public class PolDemo01 {
public static void main(String[] args) {
A a = new B(); //发生向上转型
B b = (B)a; //发生向下转型
b.fun1();
b.fun2();
b.fun3();
}
}
程序运行结果:
也就是说,以前对象只能调用自己类中的方法,发生向上转型关系后,父类对象不仅可以调用自己类中的方法,还可以调用子类中覆写父类的方法
而向下转型之后,子类对象可以调用子类、父类中的所有方法
两者都是先找被覆写过的方法,没有再调用原方法
观察以上程序向下转型过程:
public static void main(String[] args) { A a = new B(); //发生向上转型 B b = (B)a; //发生向下转型 b.fun1(); b.fun2(); b.fun3(); }
注意:在进行对象向下转型前,必须先进行对象向上转型,否则将出现对象转换异常
如下代码所示:
class A{ public void fun1(){ System.out.println("A --> public void fun1(){}"); } public void fun2(){ this.fun1(); } } class B extends A{ public void fun3(){ System.out.println("B --> public void fun3(){}"); } } public class PolDemo01 { public static void main(String[] args) { A a = new A(); //错误 ,向下转型之前没先向上转型 B b = (B)a; //发生向下转型 b.fun1(); b.fun2(); b.fun3(); } }
程序编译报错:类转换异常
为什么会出现异常呢?先从父类的定义来看:
class A{ public void fun1(){ System.out.println("A --> public void fun1(){}"); } public void fun2(){ this.fun1(); } }
从父类的定义来看,父类它本身并不确定谁是自己的子类,它不像 class B extends A{ } 这样明确确定B 继承A,为A的子类。所以直接进行向下转型就会出现类转换异常,此时,需要将两个对象建立关系,通过向上转型,“A a = new B()”,由子类去实例化父类对象,这时父类就知道自己有这么一个子类,再进行向下转型
二 、对象多态性的应用
设计一个方法,要求此方法可以接收父类的任意子类对象,并调用方法
1 、不使用对象多态性实现功能
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("C --> public void fun1(){}") ;
}
public void fun5(){
System.out.println("C --> public void fun5(){}") ;
}
};
public class PolDemo04{
public static void main(String asrgs[]){
fun(new B()) ; // 传递B的实例
fun(new C()) ; // 传递B的实例
}
public static void fun(B b){
b.fun1() ; // 调用覆写父类中的fun1()方法
}
public static void fun(C c){
c.fun1() ; // 调用覆写父类中的fun1()方法
}
};
程序运行结果:
不使用对象多态性可以实现功能,但是每增加一个子类,fun()方法就得重载一次。
2 、使用对象多态性实现功能
class A{ // 定义类A
public void fun1(){ // 定义fun1()方法
System.out.println("A --> public void fun1(){}") ;
}
public void fun2(){
this.fun1() ; // 调用fun1()方法
}
};
class B extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("B --> public void fun1(){}") ;
}
public void fun3(){
System.out.println("B --> public void fun3(){}") ;
}
};
class C extends A{
public void fun1(){ // 此方法被子类覆写了
System.out.println("C --> public void fun1(){}") ;
}
public void fun5(){
System.out.println("C --> public void fun5(){}") ;
}
};
public class PolDemo04{
public static void main(String asrgs[]){
fun(new B()) ; // 传递B的实例,产生向上转型
fun(new C()) ; // 传递B的实例,产生向上转型
}
public static void fun(A a){ //接收父类对象
a.fun1() ;
}
};
程序运行结果:
从以上程序可以发现,fun()方法使用了对象多态性,可以接收任意的子类对象,这样无论子类如何增加,fun()方法都不用改变。因为子类对象发生向上转型关系,此时父类a调用被子类覆写过的方法