一. 多态性
多态性在面向对象中是一个最重要的概念,在java中面向对象主要有以下两种主要的体现.
1. 方法的重载和覆写
2. 对象的多态性
对象的多态性主要分为以下两种类型:
(1)向上转型:子类对象->父类对象
对于向上转型,程序会自动完成,格式:
对象向上转型:父类 父类对象 = 子类实例;
(2)向下转型:父类对象->子类对象
对于向下转型时,必须明确的指明要转型的子类类型,格式:
对象向下转型: 子类 子类对象 = (子类) 父类实例;
二 . 向上转型(自动完成)
举例:
public class DuoTai {
public static void main(String[] args) {
Bemo bemo = new Bemo();//实例化子类对象
Aemo aemo = bemo;//向上转型关系
aemo.fun1();//此方法被子类覆写过
aemo.fun2();
}
}
class Aemo{//定义类A
public void fun1(){//定义fun1()方法
System.out.println("Aemo---〉public void fun1(){}");
}
public void fun2(){
this.fun1();//调用fun1()方法
}
}
class Bemo extends Aemo{
public void fun1(){//此方法被子类覆写了
System.out.println("Bemo---〉public void fun1(){}");
}
public void fun3(){
System.out.println("Bemo---〉public void fun3(){}");
}
}
运行结果:
Bemo---〉public void fun1(){}
Bemo---〉public void fun1(){}
对于以上的程序,是通过其子类进行父类对象的实例化操作的,则如果调用的方法被子类覆写过,则肯定调用被覆写过的方法。
注意点:转型之后,因为操作的是父类对象,所以是无法找到在子类中定义的新方法
三. 向下转型
将父类对象变为子类对象,称为向下转型,向下转型需要采取强制的手段。
举例:
public class DuoTai1 {
public static void main(String[] args) {
Aemo1 aemo1 = new Bemo1();//向上转型
Bemo1 bemo1 = (Bemo1)aemo1;//向下转型
bemo1.fun1();
bemo1.fun2();
bemo1.fun3();
}
}
class Aemo1{//定义类A
public void fun1(){//定义fun1()方法
System.out.println("Aemo---〉public void fun1(){}");
}
public void fun2(){
this.fun1();//调用fun1()方法
}
}
class Bemo1 extends Aemo1{
public void fun1(){//此方法被子类覆写了
System.out.println("Bemo---〉public void fun1(){}");
}
public void fun3(){
System.out.println("Bemo---〉public void fun3(){}");
}
}
运行结果:
Bemo---〉public void fun1(){}
Bemo---〉public void fun1(){}
Bemo---〉public void fun3(){}
在类B中存在3个方法,所以可以全部调用。
但是,在进行向下转型的过程中有一个问题需要注意:
就是先实例化话父类对象后,在向下转型,就会报错;
举例:
public class DuoTai1 {
public static void main(String[] args) {
Aemo1 aemo1 = new Aemo1();//向上转型
Bemo1 bemo1 = (Bemo1)aemo1;//向下转型
bemo1.fun1();
bemo1.fun2();
bemo1.fun3();
}
}
class Aemo1{//定义类A
public void fun1(){//定义fun1()方法
System.out.println("Aemo---〉public void fun1(){}");
}
public void fun2(){
this.fun1();//调用fun1()方法
}
}
class Bemo1 extends Aemo1{
public void fun1(){//此方法被子类覆写了
System.out.println("Bemo---〉public void fun1(){}");
}
public void fun3(){
System.out.println("Bemo---〉public void fun3(){}");
}
}
运行结果:
Exception in thread "main" java.lang.ClassCastException: Nisbc.club1.Aemo1 cannot be cast to Nisbc.club1.Bemo1
at Nisbc.club1.DuoTai1.main(DuoTai1.java:6)
以上的异常是在对象转型时经常发生的问题,如果两个没有关系的对象之间发生了转换关系,则肯定出线此异常。
总结:由以上的2个代码可知,在我们进行向下转型的过程中,我们必须先进行向上转型(建立和子类关系" A a = new B();")才行!
四. 对象多态性的应用
要求:设计一个方法,此方法可以接收A类中的任意子类对象,并调用方法。
不使用对象多态性,只使用方法重载:
举例:
public class DuoTai1 {
public static void main(String[] args) {
fun(new Bemo1());
fun(new Cemo1());
}
public static void fun(Bemo1 b){
b.fun1();//调用覆写父类中的fun1()方法
}
public static void fun(Cemo1 c){//这两个方法重载
c.fun1();//调用覆写父类中的fun1()方法
}
}
class Aemo1{//定义类A
public void fun1(){//定义fun1()方法
System.out.println("Aemo---〉public void fun1(){}");
}
public void fun2(){
this.fun1();//调用fun1()方法
}
}
class Bemo1 extends Aemo1{
public void fun1(){//此方法被子类覆写了
System.out.println("Bemo---〉public void fun1(){}");
}
public void fun3(){
System.out.println("Bemo---〉public void fun3(){}");
}
}
class Cemo1 extends Aemo1{
public void fun1(){//此方法被子类覆写了
System.out.println("Cemo---〉public void fun1(){}");
}
public void fun4(){
System.out.println("Cemo---〉public void fun4(){}");
}
}
运行结果:
Bemo---〉public void fun1(){}
Cemo---〉public void fun1(){}
如果按照以上的设计思路,每增加一个子类,则fun()方法就必须重载一次,如果现在有一千个子类呢?明显这样不符合要求!
此时,为了解决这样的问题,就可以使用对象的多态性完成操作。
举例:
public class DuoTai1 {
public static void main(String[] args) {
fun(new Bemo1());
fun(new Cemo1());
}
public static void fun(Aemo1 a){
a.fun1();//调用覆写父类中的fun1()方法
}
}
class Aemo1{//定义类A
public void fun1(){//定义fun1()方法
System.out.println("Aemo---〉public void fun1(){}");
}
public void fun2(){
this.fun1();//调用fun1()方法
}
}
class Bemo1 extends Aemo1{
public void fun1(){//此方法被子类覆写了
System.out.println("Bemo---〉public void fun1(){}");
}
public void fun3(){
System.out.println("Bemo---〉public void fun3(){}");
}
}
class Cemo1 extends Aemo1{
public void fun1(){//此方法被子类覆写了
System.out.println("Cemo---〉public void fun1(){}");
}
public void fun4(){
System.out.println("Cemo---〉public void fun4(){}");
}
}
运行结果:
Bemo---〉public void fun1(){}
Cemo---〉public void fun1(){}
以上代码的好处在于,不管有多少个子类对象,代码都可以轻松完成,这使用了对象多态性中的向上转型!
对象多态性可以解决方法接收参数问题。