开发者社区> 余二五> 正文

对象多态性

简介:
+关注继续查看
多态性,是面向对象的最后一个特征,也是最重要的特征,掌握多态性可以设计更好的程序结构。
 
实际上方法的重载就是一种多态性的体现:
       方法名称相同,根据传入参数的类型或个数的不同完成的功能也不同。
 
另外一种多态性就是指的对象的多态性:
       · 子类对象向父类对象转型(向上转型)
       · 父类对象向子类对象转型(向下转型)
       · 对象间的互相转型问题
 
强调:
       一个类绝对不能继承一个已经实现好了的类。此处讲解的时候只是为了阐述概念,才使用了类与类的直接继承,但是开发中此种类型的代码肯定不存在。
       观察以下程序,初步认识对象的转型:
class A{
         public void fun1(){
                   System.out.println("A --> public void fun1(){}") ;
         }
         public void fun2(){
                   this.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(){}") ;
         }
};
       以上代码可以发现,子类B,继承了父类A,同时在子类中覆写了类A中的fun1方法,也增加了自己新的fun3方法。
class A{
         public void fun1(){
                   System.out.println("A1 --> public void fun1(){}") ;
         }
         public void fun2(){
                   this.fun1() ;
         }
};
class B extends A{
         public void fun1(){
                   System.out.println("B1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("B2 --> public void fun3(){}") ;
         }
};
public class Demo10{
         public static void main(String args[]){
                   A a = new B() ;
                   a.fun1() ;
                   a.fun2() ;
         }
};
       以上代码,无论是直接使用子类,还是子类向父类转型,发现最终结果调用的都是被子类覆写过的方法。
       向上转型的关系:只要发生了向上转型,则一切的操作方法以子类为标准。
       如果向上转型完成之后,那么一定可以把父类对象变为子类对象。但是此时就需要强制了。
 
class A{
         public void fun1(){
                   System.out.println("A1 --> public void fun1(){}") ;
         }
         public void fun2(){
                   this.fun1() ;
         }
};
class B extends A{
         public void fun1(){
                   System.out.println("B1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("B2 --> public void fun3(){}") ;
         }
};
public class Demo10{
         public static void main(String args[]){
                   A a = new B() ;
                   B b = (B)a ;
                   b.fun1() ;
                   b.fun2() ;
         }
};
 
       现在观察以下代码:
class A{
         public void fun1(){
                   System.out.println("A1 --> public void fun1(){}") ;
         }
         public void fun2(){
                   this.fun1() ;
         }
};
class B extends A{
         public void fun1(){
                   System.out.println("B1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("B2 --> public void fun3(){}") ;
         }
};
public class Demo11{
         public static void main(String args[]){
                   A a = new A() ;
                   B b = (B)a ;
                   b.fun2() ;
         }
};
 
java.lang.ClassCastException
       为类型转换异常。两个没有任何关系的对象直接进行转型了,就出现此错误。
 
注意:
       如果要进行向下转型之前,首先必须建立关系,即:必须先发生向上转型之后,才可以进行向下转型。为了建立关系。
 
对象多态性所带来的好处?
       对象多态性在传递参数上可以体现出其优点,下面看两组代码,第一组是没有使用对象多态性的时候:
class A{
         public void fun1(){
                   System.out.println("A1 --> public void fun1(){}") ;
         }
         public void fun2(){
                   this.fun1() ;
         }
};
class B extends A{
         public void fun1(){
                   System.out.println("B1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("B2 --> public void fun3(){}") ;
         }
};
class C extends A{
         public void fun1(){
                   System.out.println("C1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("C2 --> public void fun3(){}") ;
         }
};
public class Demo12{
         public static void main(String args[]){
                   fun(new B()) ;
                   fun(new C()) ;
         }
         // 定义一个方法,此方法可以接收A的子类对象
         public static void fun(B b){
                   b.fun2() ;
         }
         public static void fun(C c){
                   c.fun2() ;
         }
};
       如果代码按以上格式编写会有那些问题?
       · 每增加一个子类,就要增加一个方法,所以可以发现代码重复修改。
       如果此时使用了对象多态性的概念,则代码可以修改为以下结构(所有的操作方法以被子类覆写过的方法为标准操作):
class A{
         public void fun1(){
                   System.out.println("A1 --> public void fun1(){}") ;
         }
         public void fun2(){
                   this.fun1() ;
         }
};
class B extends A{
         public void fun1(){
                   System.out.println("B1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("B2 --> public void fun3(){}") ;
         }
};
class C extends A{
         public void fun1(){
                   System.out.println("C1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("C2 --> public void fun3(){}") ;
         }
};
public class Demo13{
         public static void main(String args[]){
                   fun(new B()) ;
                   fun(new C()) ;
         }
         // 不管有多少个子类,都用父类对象接收,因为可以自动发生向上转型关系
         public static void fun(A a){
                   a.fun2() ;
         }
};
 
       感觉到一点:在继承关系中,父类的设计是最重要的,只要父类把功能定义好了,则所有代码都好写。
       新的要求:
              现在希望可以对程序的功能稍微有一些扩充,判断,如果传入的是B类对象,则可以调用fun3方法,如果传入的是C类对象,也可以调用C类的fun3方法。
       要完成此功能,肯定要使用向上转型。
       要完成此功能,必须对传入对象的类型进行判断,判断此对象到底是属于那个类的实例。
 
instanceof关键字完成:
       · 功能:判断一个对象是否是某个类的实例,返回boolean
       · 语法:对象 instanceof 
 
class A{
         public void fun1(){
                   System.out.println("A1 --> public void fun1(){}") ;
         }
         public void fun2(){
                   this.fun1() ;
         }
};
class B extends A{
         public void fun1(){
                   System.out.println("B1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("B2 --> public void fun3(){}") ;
         }
};
class C extends A{
         public void fun1(){
                   System.out.println("C1 --> public void fun1(){}") ;
         }
         public void fun3(){
                   System.out.println("C2 --> public void fun3(){}") ;
         }
};
public class Demo14{
         public static void main(String args[]){
                   fun(new B()) ;
                   fun(new C()) ;
         }
         // 不管有多少个子类,都用父类对象接收,因为可以自动发生向上转型关系
         public static void fun(A a){
                   a.fun2() ;
                   if(a instanceof B){
                            B b = (B)a ;
                            b.fun3() ;
                   }
                   if(a instanceof C){
                            C c = (C)a ;
                            c.fun3() ;
                   }
         }
};
 
转型原则:
       在转型之前最好先判断一下一个对象是否是某个类的实例,判断通过之后在进行向下转型操作。
 
转型概念清楚之后就可以利用此概念完善抽象类与接口。









本文转自 李兴华 51CTO博客,原文链接:http://blog.51cto.com/lixinghua/91245,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
基类与派生类对象的关系 派生类的构造函数
🐰 基类与派生类对象的关系 🐰派生类的构造函数
8 0
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)
184 0
C++继承与派生解析(继承、重载/转换运算符、多重继承、多态、虚函数/纯虚函数、抽象类)
C++继承与派生解析(继承、重载/转换运算符、多重继承、多态、虚函数/纯虚函数、抽象类)
78 0
反射获取类对象
反射获取类对象
25 0
继承与多态(1)
继承与多态(1)
34 0
C++多态性原理详解(静态多态、动态多态、虚函数、虚函数表)
C++多态性原理详解(静态多态、动态多态、虚函数、虚函数表)
154 0
【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )(二)
【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )(二)
102 0
【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )(一)
【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )(一)
1367 0
面向对象——继承与构造函数
面向对象——继承与构造函数
66 0
虚方法和多态
以来倒置原则程序与设计要以来抽象(Pet)类,而不依赖于具体类(Dog)
348 0
+关注
余二五
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
建立联系方法之一
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载