5.8面向对象(*多态)

来源:互联网 发布:mac妆前乳专柜价格 编辑:程序博客网 时间:2024/05/29 18:05

1多态

1.1多态特点

  • 需要继承
  • 父类引用指向子类
  • 方法的覆盖(需要函数名相同,参数相同)
  • 抽象类


1.2父类引用指向子类

上栗子:Animal类

/*动物类*/class Animal{//动物有的属性String type;//带参数的构造器public Animal(String type){this.type = type;}//动物都有的行为(叫)public void call(){System.out.println(type+"在叫");}}
Dog类:

/*狗类*/class Dog extends Animal{//dog自己的一些属性String color;String hair;//添加构造器public Dog(){super("小狗");//调用构造函数this.color = "黑色";this.hair = "卷毛";}//覆盖父类(叫)的行为,要函数名,参数都一样public void call(){System.out.println(color+hair+"的"+this.type+"在叫");}}
main:

public static void main(String[] args) {//父类引用指向了子类Animal a = new Dog();                Dog dog = (dog) a;  //这样就可以强制转换成Dog                                a.call(); //输出:黑色卷毛的小狗在叫}
看main方法中,父类Animal用子类来实例化,Dog 就可以指向a了

其实在用Dog来实例化是  a  不仅指向内部的父类,还有一根虚线指向外部的父类(图中红线)

看内存模型:



1.3方法的覆盖

main代码中最后一行是用a.call(),来调用用方法,为什么输出的结果与想象中的不一样呢?

那是因为在Dog类中,在写了一个与父类名字相同,参数相同的方法,这样就会覆盖了父类原有的方法,这是调用就只会调用Dog子类中的方法,这就是多态。


1.4抽象类

  • 作用:就是用来被继承和函数的覆盖
  • 有一个抽象函数的类就叫抽象类
  • 该类不能实例化
  • 子类一定要覆盖父类的抽象方法

例:将Animal类抽象

/*动物类*/abstract class Animal{//有了抽象方法,类名前面也加abstract关键字,否者会编译报错//动物有的属性String type;//带参数的构造器public Animal(String type){this.type = type;}//将call方法抽象public abstract void call();//在返回值前面添加abstract关键字,并且抽象方法没有语句块,直接“;”结束}
Dog类不变,直接main:

public static void main(String[] args) {//*抽象类不能实例化,否者会报错//Animal a = new Animal("xiaogou")Dog d = new Dog();d.call(); //输出:黑色卷毛的小狗在叫}


1.5,为什么要抽象化

抽象其实就是给我们确定了一种规则:

如我们要用多态,就需要父类引用指向子类,子类要覆盖父类的方法,如果不小心把覆盖方法名写错了,这样是不会报错的,因为父类中有该方法。

例:如果将Dog中call()方法写成calll(),这样方法与父类的就不相同,也就不会形成覆盖

//覆盖父类(叫)的行为,要函数名,参数都一样(不小心写错了)public void calll(){System.out.println(color+hair+"的"+this.type+"在叫");}
运行也不会报错,但这样输出的结果就会与预期的不一样,这样的问题就不好找到

如果抽象化了,子类就一定要覆盖这个抽象方法,要不就会报错,这样就把错误暴露出来,一下就能找到




0 0