我觉得一个高水平的老师可以知识讲解的简单明了,而一个低水平的老师则会把知识更加复杂化,讲解的晦涩难懂。原因在于其没有深刻的理解,抓住事物的本质特征。其讲解的复杂度也就负相关于了学生的理解接收程度。因此本博客写作力求深刻理解事物本质,然后用简洁明了的语言将其阐述清楚。
多态,一个引用变量的多种状态。具体一点就是,程序定义的父类引用变量所指向的子类对象在编程时是不确定的,而是在程序运行期间确定的。怎么理解?看下面代码,现在讲太多道理太空洞。
public class Test12 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Animal1 a= new Cat1();
a.speak();
a =new Dog1();
a.speak();
}
}
class Animal1{
String name;
int age;
public void speak(){
System.out.println("我是动物,不知道怎么叫!!");
}
}
class Cat1 extends Animal1{
//Overriding
public void speak(){
System.out.println("我是小猫,喵喵喵!");
}
}
class Dog1 extends Animal1{
//Overriding
public void speak(){
System.out.println("我是小狗,汪汪汪!");
}
}
可以看到,同一个引用变量 a ,在不同的时刻既可以指向new Cat(),又可以指向new Dog()。这就是“多态”。
慢着,以前我们在创建一个类的对象时,是这样的Cat cat=new Cat(),但是却是这样Animal a=new Cat();。这样做可以吗?
答案是肯定的。由于Cat可以自动“向上转型”为Animal,所以 a 是可以指向Cat 的实例对象的。“向上转型”的概念是初次接触,本来应该加以介绍,限于篇幅所限,暂且按住不表。留待下文分解。
继续说“多态”,看下面Code
public class Test12 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Animal1 a= new Cat1();
a.speak();
a.eat();
a =new Dog1();
a.speak();
}
}
class Animal1{
String name;
int age;
public void speak(){
System.out.println("我是动物,不知道怎么叫!!");
}
}
class Cat1 extends Animal1{
//Overriding
public void speak(){
System.out.println("我是小猫,喵喵喵!");
}
public void eat(){
System.out.println("我是小猫,我爱吃鱼!");
}
}
class Dog1 extends Animal1{
//Overriding
public void speak(){
System.out.println("我是小狗,汪汪汪!");
}
}
在上一个code的基础上,为Cat增加的eat()方法,并且用父类引用a来调用。可以吗?我们发现编译都编不过去。在a.eat() 处报错。eclipse 提示“The method eat() is undefined for the type Animal1” 。
看看,提示的很清楚!说明什么,说明现在父类引用a 的类型是animal ,不是Cat,因此它能够调用的只能是animal中存在的方法,如果animal中不存在,则无法调用。
再看code
public class Test12 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Animal1 a= new Cat1();
a.speak();
a.eat();
a =new Dog1();
a.speak();
}
}
class Animal1{
String name;
int age;
public void speak(){
System.out.println("我是动物,不知道怎么叫!!");
}
public void eat(){
System.out.println("我是动物,我就要吃!");
}
}
class Cat1 extends Animal1{
//Overriding
public void speak(){
System.out.println("我是小猫,喵喵喵!");
}
}
class Dog1 extends Animal1{
//Overriding
public void speak(){
System.out.println("我是小狗,汪汪汪!");
}
}
在上面的code中,在animal中写了eat()方法,然后在父类引用a 处调用eat()方法,完全正确。
总结一下,在实现多态以后,父类引用的类型是父类的类型,而不是子类的类型;父类引用可以调用的方法是被子类继承或者重写的方法。