概念:
百度百科:
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。
允许将子类类型的指针赋值给父类类型的指针。
作用:
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
特性:
赋值之后,父类型的引用就可以根据当前赋值给它的子对象的特性以不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲。
简而言之:编译看左边,运行看右边
说明:
A a = new A();
一个对象是类的一个实例
这里new A()才是创建了一个对象,而a只是一个指向这个对象的一个引用(可以理解为指针)
举例:
Father类
public class Father {
//父亲的方法show()供儿子们继承
public void show() {
System.out.println("I am a father. I have two sons.");
}
//父亲独有的方法somking()
public void smoking() {
System.out.println("A cigarette after dinner");
}
}
Son1类继承了Father
public class Son1 extends Father{
//Son1继承父亲的方法show()
public void show() {
System.out.println("I'm a big brother Son1");
}
//Son1独有的方法do_homework()
public void do_homework() {
System.out.println("Son1 doing homework");
}
}
Son2类继承了Father
public class Son2 extends Father{
//Son2继承父亲的方法show()
public void show() {
System.out.println("I'm a little brother Son2");
}
//Son2独有的方法play_game()
public void play_game() {
System.out.println("Son2 Playing games");
}
}
主函数
public class Polymorphism_main {
public static void main(String[] args) {
//父类引用指向子类对象,此时子类会向上转型成父类
Father father1 = new Son1();
Father father2 = new Son2();
//此时father1和father2都是Father类型的引用(指针),但是指向的是子类Son1和Son2对象
//编译时看左边Father类中有没有show()方法,运行时看右边Son1,Son2类中有没有重写show()方法
//有重写则调用Son1和Son2中的show()方法
father1.show();
father2.show();
//这里Son1,Son2中没有对Father的smoking()进行重写,所以会调用Father中的smoking()方法
//子类会继承父类的非私有方法
father1.smoking();
father2.smoking();
}
}
结果
I'm a big brother Son1
I'm a little brother Son2
A cigarette after dinner
A cigarette after dinner
如果father1和father2这两个父类引用调用子类Son1,Son2独有的方法
//如果父类引用调用子类对象的独有的方法
//编译时看左边Father中有没有do_homework()方法,这里会报“没有为Father定义方法do_homework()”的错误
//注意:这里father1引用(指针)指向的是Son1的一个对象所以在对象创建(数据存储)过程中包含了所有Son1的变量和方法
//只不过这个引用(指针)的类型是Father所以不能调用Son1独有的方法
//father1.do_homework();
//father2.play_game();
//如果想调用子类独有的方法,则需要强制向下转型
//这里son1只是把Father类型的引用(指针)father1重新定义为Son1类型的引用(指针)
//因为father1指向的是Son1的一个对象,这个对象在创建的时候肯定包含了Son1的所有变量和方法
//这里只不过是把引用(指针)的类型重新定义为Son1
Son1 son1 = (Son1)father1;
son1.do_homework();
Son2 son2 = (Son2)father2;
son2.play_game();
结果
Son1 doing homework
Son2 Playing games
那么能不能子类引用指向父类对象呢?
//这里直接写会报类型不匹配的错误
//Son1 son1 = new Father();
//那么如果进行强制转换的话,编译的时候不会报错
//但运行的时候会报"Polymorphism.Father cannot be cast to Polymorphism.Son1"的异常
//因为这里是不安全的Father中不一定包含了Son1的所有变量和方法
//比如这里Son1中的do_homework()方法则不包含
Son1 son1 = (Son1)new Father();
//注意:当创建一个子类对象时指向这个对象的引用(指针)可以是这个子类类型或者是这个子类的父类类型,
//但是如果创建的是一个父类对象则指向这个对象的引用(指针)就不能用这个父类的子类类型的指针来指向
总结:
父类引用指向子类对象
Father father = new Son()
创建这个子类对象的时候内存中肯定包含了所有父类的变量和方法,因为子类继承了父类的所有非私有的变量和方法
所以用father引用Father中方法的时候在内存中是存在父类的方法的,又因为这里创建的是子类的对象所以内存中还包含了子类的所有独有变量和方法,只不过是使用Father类型的指针指向的,所有不能使用子类独有的方法,但是如果重新定义指针的类型即Son son = (Son) father,把指针类型定义成子类的类型就可以使用子类独有的方法了。
子类引用指向父类对象
Son son = new Father()
创建这个父类对象的时候,内存中只有该父类的所有变量和方法没有子类的,因为父类不能继承子类的非私有变量和方法
所以当用这个子类引用son使用某个父类对象中没有而子类对象中独有的方法的时候就会出现内存中找不到该方法的情况,是不安全的
当创建一个子类对象时指向这个对象的引用(指针)可以是这个子类类型或者是这个子类的父类类型,
但是如果创建的是一个父类对象则指向这个对象的引用(指针)就不能用这个父类的子类类型的指针来指向