面向对象——多态
2016-06-07 10:28
176 查看
对象的多态性
多态性在面向对象是一个最重要的概念,在Java中面向对象主要有以下两种主要体现:方法的重载和覆写
对象的多态性
关于方法的重载和覆写的区别
区别点 | 重载 | 覆写 |
---|---|---|
单词 | Overloading | Overriding |
定义 | 方法名称相同,参数和类型或个数不同 | 方法名称、参数的类型、返回值类型全部相同 |
对权限没有要求 | 被覆写的方法不能拥有更严格的权限 | |
范围 | 发生在一个类中 | 发生在继承类中 |
对象的多态性只要分为以下两种类型
对象向上转型:父类 父类对象= 子类实例
对象向下转型:子类 子类对象 =(子类)父类实例
那为什么要进行对象的转型呢?
通过下面两个例子来看看
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(){}"); } } public class Demo01 { public static void main(String[] args) { A a = new B(); //向上转型 子类——>父类 a.fun1(); } } /* 运行结果: B————>public void fun1(){} */
上面的程序使用了对象的向上转型,虽然使用了 父类调用了fun1方法,但是调用的是被子类覆写的方法。
也就是说,如果对象发生了向上转型关系后,所调用的方法一点是被子类覆写过的方法。
那么,如果我们要调用子类自己的定义的方法fun3(),就无法通过对象a来调用。
如果想要调用子类自己的方法,则肯定要使用子类的实例,所有此时可以将对象进行向下转型。
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(){}"); } } public class Demo02 { public static void main(String[] args) { A a = new B(); B b = (B)a;//向上转型,首先要进行乡下转型 b.fun1(); b.fun2(); b.fun3(); } } /* B————>public void fun1(){} B————>public void fun1(){} B————>public void fun3(){} */
从以上的程序可以发现,如果要调用子类自己的方法,则一定要用子类声明对象,另外,在子类调用父类的fun2方法,fun2方法要调用fun1方法,但此时的fun1方法已经被子类覆写,则调用的是被子类覆写的方法。
现在我们清晰了重写和重载还有对象多态性的概念了,下面我们来看一道非常经典的题目来加深我们的理解。
class A { public String show(D obj){ return ("A and D"); } public String show(A obj){ return ("A and A"); } } class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } } class C extends B{} class D extends B{} public class Demo { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); //1 System.out.println(a1.show(c)); //2 System.out.println(a1.show(d)); //3 System.out.println(a2.show(b)); //4 System.out.println(a2.show(c)); //5 System.out.println(a2.show(d)); //5 System.out.println(b.show(b)); //6 System.out.println(b.show(c)); //7 System.out.println(b.show(d)); //8 } } /* 运行结果: A and A A and A A and D B and A B and A A and D B and B B and B A and D */
当B继承A之后,实际上B中有3个方法
public String show(B obj){
return (“B and B”);
}
public String show(A obj){
return (“B and A”);
}
public String show(D obj){
return (“A and D”);
}
先分析一下A类中的方法,show(D obj),show(A obj),这两个方法在内部达成了重构,重载后,会优先选择最适合的方法,没有最合适的方法会调用能使用的方法。
先看 A a1 = new A()
第一个 a1.show(b) 调用A类中的方法,内部构成重载,找不到最合适的方法,所以会调用show(A obj) 因为 b是B的对象,而B是A的子类,所以可以传入输出 A and A
第二个a1.show(c) 同上 输出A and A
第三个a1.show(d) 重载会优先选择最适合的方法,就会调用show(D obj),输出A and D
再分析一下B类中的方法
里面有这两个方法 ,show(A obj)覆写了A类的中的show(A obj),内部重载
分析完了B类
再看 A a2 = new B() 实现了对象的向上转型
相当于a2中有A类中show(D obj) 和被B类覆写的方法
public String show(D obj){
return (“A and D”);
}
public String show(A obj){
return (“B and A”);
}
a2.show(b)
a2是A的实例对象,只能调用A中的方法,无法调用B类中的私有方法。内部重构,调用show(A obj),由于实现了对象的向上转型,而且show(A obj)被覆写,会调用子类覆写的方法,输出B and A
a2.show(c) 同上,输出B and A
a2.show(d) 调用 show(D obj) ,输出 A and D
B b = new B();
b.show(b) 这个比较简单, 输出B and B
b.show(c) 重构,优先原则 输出 B and B
b.show(d) 因为B是A的子类,就直接调用父类的的show(D obj) 输出 A and D
个人理解,有误解的地方,欢迎在底下给我留言。
相关文章推荐
- Lua编程示例(二):面向对象、metatable对表进行扩展
- C#与.net高级编程 C#的多态介绍
- C#中面向对象编程机制之多态学习笔记
- 浅谈Lua的面向对象特性
- Lua面向对象之类和继承浅析
- JavaScript面向对象的两种书写方法以及差别
- 浅谈c# 面向对象之类与对象
- C#中的多态深入理解
- C#面向对象特征的具体实现及作用详解
- C# 面向对象的基本原则
- C#中多态、重载、重写区别分析
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- 浅谈对c# 面向对象的理解
- Ruby面向对象编程详解
- C# 面向对象三大特性:封装、继承、多态
- php学习 面向对象 课件第1/2页
- PHP程序61条面向对象分析设计的经验小结
- 收集学习asp.net比较完整的面向对象开发流程
- Python3 面向对象概述
- java面向对象之类和对象