多态
体现
父类的引用或者接口的引用指向了自己的子类对象。
Dog d = new Dog();//Dog对象的类型是Dog类型。
Animal a = new Dog();//Dog对象的类型右边是Dog类型,左边Animal类型。
//多态
class Dog extends Animal
{
public void eat()
{
System.out.println("骨头");
}
public void lookHome()
{
System.out.println("看家");
}
}
//描述猫
class Cat extends Animal
{
public void eat()
{
System.out.println("鱼");
}
public void catchMouse()
{
System.out.println("抓老鼠");
}
}
//进行抽取。将共性的功能抽取到父类Animal中。
abstract class Animal
{
public abstract void eat();
}
好处
提高了程序的扩展性。
弊端
通过父类引用操作子类对象时,只能使用父类中已有的方法,不能操作子类特有的方法。
前提
1,必须有关系:继承,实现。
2,通常都有重写操作。
子类的特有方法如何调用呢?
Animal a = new Dog();//Animal是父类型,new Dog()是子对象。
但是父类型引用指向子类对象时,这就是让子类对象进行了类型的提升(向上转型)。
向上转型好处:提高了扩展性,隐藏了子类型。弊端:不能使用子类型的特有方法。
如果要想使用子类的特有方法,只有子类型可以用。
可以向下转型,强制转换。
Animal a = new Dog();
a.eat();
Dog d = (Dog)a;//将a转型为Dog类型。向下转型。
d.lookHome();
向下转型什么时候用?当需要使用子类型的特有内容时。
注意:无论向上还是向下转型,最终都是子类对象做着类型的变化。
向下转型的注意事项
Animal a = new Dog();
//Cat c = (Cat)a;向下转型因为不明确具体子类对象类型,所以容易引发ClassCastException异常。
所以为了避免这个问题,需要在向下转型前,做类型的判断。
判断类型用的是关键字 instanceof
if(a instanceof Cat)//a指向的对象的类型是Cat类型。
{
//将a转型Cat类型。
Cat c = (Cat)a;
c.catchMouse();
}
else if(a instanceof Dog)
{
Dog d = (Dog)a;
d.lookHome();
}
转型总结
1,什么时候使用向上转型呢?
提高程序的扩展性,不关系子类型(子类型被隐藏)。
需要用子类的特有方法吗?不需要,哦了。向上转型。
2,什么时候使用向下转型呢?
需要使用子类型的特有方法时。
但是一定要使用 instanceof 进行类型的判断。避免发生 ClassCastException
多态成员调用的特点
成员变量
当子父类中出现同名的成员变量时。
多态调用该变量时:
编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。
运行时期:也是调用引用型变量所属的类中的成员变量。
简单记:编译和运行都参考等号的左边。
编译运行看左边。
对于成员函数是动态绑定到对象上。
class Fu
{
int num = 3;
}
class Zi extends Fu
{
int num = 5;
}
class DuoTaiDemo3
{
public static void main(String[] args)
{
Fu f = new Zi();
System.out.println(f.num);//3
Zi z = new Zi();
System.out.println(z.num);//5
}
}
成员函数
编译,参考左边,如果没有,编译失败。
运行,参考右边的对象所属的类。
编译看左边,运行看右边。
对于成员函数是动态绑定到对象上。
class Fu
{
void show()
{
System.out.println("fu show run");
}
}
class Zi extends Fu
{
void show()
{
System.out.println("zi show run..");
}
}
class DuoTaiDemo3
{
public static void main(String[] args)
{
Fu f = new Zi();
//zi show run..
f.show();
}
}
静态函数
编译和运行都参考左边。
静态函数是静态的绑定到类上。
class Fu
{
static void method()
{
System.out.println("fu static method run");
}
}
class Zi extends Fu
{
static void method()
{
System.out.println("zi static method run");
}
}
class DuoTaiDemo3
{
public static void main(String[] args)
{
Fu f = new Zi();
//fu static method run
f.method();
//注意:真正开发静态方法是不会被多态调用的,因为静态方法不所属于对象,而是所属于类。
//fu static method run
Fu.method();
//fu static method run
Zi.method();
}
}
结论
对于成员变量和静态函数,编译和运行都看左边。
对于成员函数,编译看左边,运行看右边。
网友评论