概念
现实事物经常会体现出多种形态,如猫是动物的一种:一只猫咪,既是猫也是动物,即出现两种形态。
Java可以描述这种关系,猫类继承了动物类,猫这类事物的对象便既是猫,又是动物。
多态在代码中的体现:
父类或者接口的引用指向其子类的对象
package com.monfolld;
public abstract class Animal {
public abstract void eat();
}
class Cat extends Animal{
public void eat(){
System.out.println("鱼");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗");
}
public void lookHome(){
System.out.println("看家");
}
}
class Pig extends Animal
{
public void eat()
{
System.out.println("饲料");
}
void gongDi()
{
System.out.println("拱地");
}
}
class polymorphic{
public static void main(String[] args){
Cat c=new Cat();
Dog d=new Dog();
method(c);method(d);//可传入的对象具有多态性
method(new Pig());
}
public static void method( Animal a) //Animal a=new Dog();
{
a.eat();
}
}
多态的好处:提高点代码的扩展性,前期定义的代码可以使用后期的内容.
多态的弊端:前期定义的内容不能使用(调用)后期子类的特有内容
多态的前提:
1.必须有关系,继承,实现.
2.要有覆盖.
多态-转型
自动类型提升,猫对象提升了动物类型,但是特有功能无法访问
作用就是限制对待特有功能的访问
专业讲:向上转型.
Animal a=new Cat ();
a.eat();
如果还想用具体动物猫的特有功能,可以进行向下转型,向下转型的目的是为了使用子类中的特有方法.
Cat c=(Cat)a;
c.eat();
c.catchMouse();
注意:对于转型,自始至终都是子类对象在做着类型的变化。
下面是一个例子:
package com.monfolld;
class Fu{
void sperk()
{
System.out.println("Fu");
}
void 钓鱼(){
System.out.println("钓鱼");
}
}
class Zi extends Fu{
void speak(){
System.out.println("Zi");
}
void 看电影(){
System.out.println("看电影");
}
}
public class Zhuanxing {
public static void main(String[] args){
Fu f=new Zi();// 向上转型
f.sperk(); //Fu里面的内容 输出:Fu
f.钓鱼(); //Fu里面的内容 输出:钓鱼
Zi z=(Zi)f; // 向下转型
z.speak(); //Zi里面的内容 输出:Zi
z.看电影(); //Zi里面的内容 输出:看电影
}
}
各成员的特点
成员变量:
编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边。
成员函数(非静态):
编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。(先找子类,如果子类没有,再找父类),因为成员函数存在覆盖特性。
静态函数:
编译时:参考引用型变量所属的类中的是否有调用的静态方法。
运行时:参考引用型变量所属的类中的是否有调用的静态方法。
简单说,编译和运行都看左边。(静态方法直接看哪个类调用的就好了,不存在覆盖。)
其实对于静态方法,是不需要对象的。直接用类名调用即可。