您的位置:首页 > 其它

面向对象——多态

2016-06-07 10:28 176 查看

对象的多态性

多态性在面向对象是一个最重要的概念,在Java中面向对象主要有以下两种主要体现:

方法的重载和覆写

对象的多态性

关于方法的重载和覆写的区别

区别点重载覆写
单词OverloadingOverriding
定义方法名称相同,参数和类型或个数不同方法名称、参数的类型、返回值类型全部相同
对权限没有要求被覆写的方法不能拥有更严格的权限
范围发生在一个类中发生在继承类中
对象的多态性

对象的多态性只要分为以下两种类型

对象向上转型:父类 父类对象= 子类实例

对象向下转型:子类 子类对象 =(子类)父类实例

那为什么要进行对象的转型呢?

通过下面两个例子来看看

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

个人理解,有误解的地方,欢迎在底下给我留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面向对象 多态