多态:字面意思讲,就是某一类事物的多种形态。简单来说,就是一个对象对应着多个类型
1.多态在代码中的体现:
父类或者接口的引用指向了其子类对象。
2.多态的好处:
1.提高了代码的扩展性,前期定义的代码可以使用后期的内容。
//先定义Cat类型继承Animal类,后期定义Dog类,同样使用先前定义好的method方法
public class Duotai{
public static void main(String[]args){
Animal c = new Cat();
Animal d = new Dog();
method(c);
method(d);
}
public static void method(Animal a){
a.eat();
}
//定义Animal抽象类
abstract class Animal{
abstract void eat();
}
//创建Dog类继承Animal抽象类并实现其中的方法
class Dog extends Animal{
void eat(){
System.out.println("啃骨头");
}
void lookHome(){
System.out.println("看家");
}
}
//创建Cat类继承Animal抽象类并实现其中的方法
class Cat extends Animal{
void eat(){
System.out.println("吃鱼");
}
void catchMouse(){
System.out.println("抓老鼠");
}
}
运行结果如下:
Compiling Duotai.java……
——Output——
吃鱼
啃骨头
[Finished in 0.6s]
2.多态的弊端:
前期定义的内容不能使用后期子类的特有内容,因为在Animal c = new Cat()的时候,Cat对象提升为了动物类型,所以特有的方法无法访问。
public class Duotai{
public static void main(String[]args){
Animal c = new Cat();
Animal d = new Dog();
c.catchMouse();
d.lookHome();
}
}
//定义Animal接口
abstract class Animal{
abstract void eat();
}
//创建Dog类继承Animal抽象类并实现其中的方法
class Dog extends Animal{
void eat(){
System.out.println("啃骨头");
}
void lookHome(){
System.out.println("看家");
}
}
//创建Cat类继承Animal抽象类并实现其中的方法
class Cat extends Animal{
void eat(){
System.out.println("吃鱼");
}
void catchMouse(){
System.out.println("抓老鼠");
}
}
结果如下:两个子类对象因向上转型而无法访问其特有方法
Compiling Duotai.java……
Duotai.java:228: 错误: 找不到符号
c.catchMouse();
^
符号: 方法 catchMouse()
位置: 类型为Animal的变量 c
Duotai.java:229: 错误: 找不到符号
d.lookHome();
^
符号: 方法 lookHome()
位置: 类型为Animal的变量 d
2 个错误
[Finished in 0.6s]
解决弊端问题:
所以要想使用子类中特有的功能的时候,可以对对象进行向下转型,就可以使用子类中的特有方法。
public class Duotai{
public static void main(String[]args){
Animal c = new Cat();
Cat a = (Cat)c;
a.eat();
a.catchMouse();
Animal d = new Dog();
Dog b = (Dog)d;
b.eat();
b.lookHome();
}
}
//定义Animal接口
abstract class Animal{
abstract void eat();
}
//创建Dog类继承Animal抽象类并实现其中的方法
class Dog extends Animal{
void eat(){
System.out.println("啃骨头");
}
void lookHome(){
System.out.println("看家");
}
}
//创建Cat类继承Animal抽象类并实现其中的方法
class Cat extends Animal{
void eat(){
System.out.println("吃鱼");
}
void catchMouse(){
System.out.println("抓老鼠");
}
}
结果如下:
Compiling Duotai.java……
——Output——
吃鱼
抓老鼠
啃骨头
看家
[Finished in 0.6s]
3.注意:
对于转型,自始至终都是子类对象在做着类型的变化。在转型前,一般用instanceof进行类型的判断,以增强代码的健壮性。
4.多态时成员的特点
1.成员变量:
编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,没有,编译失败。
public class DuotaiDemo{
public static void main(String [] args){
Fu f = new Zi();//向上转型成为了Fu类
System.out.println(f.num);//调用了Fu类中没有的成员变量,编译失败
}
}
class Fu{
}
class Zi extends Fu{
int num=3;
}
结果如下:
Compiling DuotaiDemo.java……
DuotaiDemo.java:6: 错误: 找不到符号
System.out.println(f.num);
^
符号: 变量 num
位置: 类型为Fu的变量 f
1 个错误
[Finished in 0.5s]2.运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
public class DuotaiDemo{
public static void main(String [] args){
Fu f = new Zi();
System.out.println(f.num);
}
}
class Fu{
int num=5;
}
class Zi extends Fu{
int num=3;
}
结果如下:可以看出来结果是向上转型后的类的结果
Compiling DuotaiDemo.java……
——Output——
5
[Finished in 0.6s]
简单来说:在对于多态中的成员变量时,编译和运行都参考等号的左边。
2.成员方法(非静态)
编译时:参考引用型变量所属的类中是否有调用的方法,有,编译通过,没有,编译失败。
public class DuotaiDemo{
public static void main(String [] args){
Fu f = new Zi();//在此处对象向上转型成了Fu类型对象
f.show();//Fu类型中没有show()方法,编译失败;
}
}
class Fu{
}
class Zi extends Fu{
void show(){
System.out.println("zi show");
}
}
运行时:参考对象所属的类中是否有调用的方法,子类方法会覆盖父类的方法
Compiling DuotaiDemo.java……
——Output——
zi show
[Finished in 1.0s]
public class DuotaiDemo{
public static void main(String [] args){
Fu f = new Zi();
f.show();
}
}
class Fu{
void show(){
System.out.println("fu show");
}
}
class Zi extends Fu{
void show(){
System.out.println("zi show");
}
}
结果如下
简单说:编译看左边,运行看右边
3.静态方法
编译时:参考对象所属类中是否有调用的静态方法
运行时:参考对象所属类中是否有调用的静态方法
简单说:编译和运行都看左边
其实对于静态方法,是不需要对象的,直接用类名调用
public class DuotaiDemo{
public static void main(String [] args){
Fu f = new Zi();
f.show();
f.method();
}
}
class Fu{
void show(){
System.out.println(“fu show”);
}
static void method(){
System.out.println(“Fu static method”);
}
}
class Zi extends Fu{
void show(){
System.out.println(“zi show”);
}
static void method(){
System.out.println(“zi static method”);
}
}
结果如下:当方法是静态的时,输出的是对象所属类的静态方法
当方法不是静态时,输出的是引用型变量所属类中的方法
Compiling DuotaiDemo.java……
——Output——
zi show
Fu static method
[Finished in 0.6s]