Java之类的多态,向上转型,方法覆写,抽象类一次弄懂

类的多态

类的多态 =》向上转型 + 方法覆写
先来回顾一下类的实例化

类名 引用=new 类名();
Animal animal = new Animal();
Cat cat = new Cat();
Dog dog = new Dog();

下面有三个类,动物类,猫类和狗类继承动物类。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.向上引用

向上引用最大意义在于参数统一化。可以用一个父类引用,接收所有子类实例。

向上引用发生在三个地方:

1.1直接赋值

父类名 父类引用=new 子类实例();

public class Test {
    public static void main(String[] args) {
        Animal animal=new Animal("动物",6);
        Animal cat=new Cat("毛毛",3);
        Animal dog=new Dog("旺财",4);
        animal.eat("食物");
        cat.eat("猫粮");
        dog.eat("狗粮");
  }
}

在这里插入图片描述

1.2.方法函数参数

public class Test {
    public static void main(String[] args) {
        Animal animal=new Animal("动物",6);
        Cat cat=new Cat("毛毛",3);
        Dog dog=new Dog("旺财",4);
        
        fun(animal,"食物");  /**  向上转型**/
        fun(cat,"猫粮");
        fun(dog,"狗粮");
    }
    public static void fun(Animal animal,String food){
        animal.eat(food);
    }
}

结果:fun()函数的参数是Animal类,但输入Cat和Dog类也成功了,因为这时发生了向上转型,猫类和狗类是动物类的子类,有天然继承关系。即猫类和狗类 是 动物类。
在这里插入图片描述

1.3.函数返回值

public class Test {
    public static void main(String[] args) {
        Animal animal=test();
        animal.eat("美味");
    }
    public static Animal test(){
        return new Dog("GOU",6);   /** 向上转型 **/
    }
}

结果:test()函数实际返回Dog类型与声明Animal类型不冲突,此时发生向上转型,Dog 是天然的Animal类。
在这里插入图片描述

2.方法覆写(override)

2.1 概念

方法覆写:对于存在继承关系的类时,子类定义了与父类完全相同的方法。

方法重载:在一个类中,定义若干个方法名字相同,但是参数列表不同(参数类型,参数个数)的方法。

问题:父类和子类都有eat方法,那么到底调用哪个类的eat()方法?

回答:看是哪个类new 出来的对象,就调用哪个类的方法。上述三个地方都发生了向上引用,但是eat()方法都是由new 出来的类实现的。

        Animal animal=new Animal("动物",6);
        Animal cat=new Cat("毛毛",3);
        Animal dog=new Dog("旺财",4);
        animal.eat("食物");
        cat.eat("猫粮"); //看是谁 new 出来的
        dog.eat("狗粮");

2.2 方法覆写三大要求:

只能重写成员方法/实例方法,不能覆写静态(static)方法(方法重载可以)

下图,给Dog类覆写父类静态方法出错
在这里插入图片描述

子类方法的权限修饰 >= 父类
父类是public ,子类只能是public
父类是包,子类可以是包或public

问:当父类使用private的方法,子类使用public 覆写该方法是否成功?
答:不能

包访问权限:只有同级目录下的类之间可见。
方法覆写时主义是否在同一目录下。

方法覆写的返回值必须相同,至少是向上转型

在这里插入图片描述

3.向下转型

3.1 概念

向下转型:(要能发生向下转型,必须先发生向上转型)-强制发生类型转换。

一定可以向下转型? 不一定=父类不一定是子类类型 dog is an animal ->animal is a dog?

Animal animal=new Dog();
Dog dog=(dog)animal;

这里可以发生向下转型,是因为animal本质是Dog类的,只是用父类引用,所以可以向下转型。

什么时候使用向下转型? 当使用子类独有的方法时,需要将父类的引用还原
在这里插入图片描述

在这里插入图片描述

向下转型是有风险的,若强制转型的两个类没有关系,会出错

Cat cat=new Cat();
Dog dog=(Dog)cat;    //出错,两个类没有关系

3.2 instanceof 关键字

引用 instanceof类,表示该引用是否指向这个类的实例

在这里插入图片描述
大坑: 下面代码结果是多少?

class A{
    public A(){
        this.func();
    }
    public void func(){
        System.out.println("A 的 func");
    }
}
public class B extends A{
    private int num;
    public B(int num){
        this.num=num;
    }
    public void func(){
        System.out.println("B 的 func"+"num ="+num);
    }

    public static void main(String[] args) {
        new B(100);
    }
}

结果:
在这里插入图片描述
下面为new B(100)的实例化过程

private int num;
public B(int num)
 {
  super();//  B继承A,先调用A类的无参构造
  int num=100this.num=num;
  }

super()调用A类的构造方法-》调用func函数

但A类和B类都有func函数,调哪一个?
new B();由B类new 出来的,所以,覆写方法调用B类中的func函数,同时num默认赋值为0;

4. final关键字

final关键字(终结器)

1.修饰属性,表示该属性为常量,不能修改
2.修饰类,表示该类不能有子类
3.修饰方法,表示该方法不能被覆写

byte b1=1,b2=2,b3,b4,b5;
final byte b6=4,b7=7,b8=9;
//以下哪个是对的?
b3=b1+b2;1)
b4=b6+b7;2)
b5=b1+b6;3)
b8=b2+b7;4

答案:只有(2)是正确的;
(1)错,byte类型在存储时会转为 int 类型,所以byte运算时要注意强转 b3=(byte) b1+b2;
(2)对,final 定义byte值,不仅值不能变,类型也不会变,所以(2)正确。
(3) 错,int +byte =int
(4)错,final byte 值不能变

5.多态

多态性:如下图所示,fun函数通过一个引用,可以输出多种状态
在这里插入图片描述
多态的好处:

1.使用门槛低
2.方便扩展

多态主要是 :向上转型 + 方法覆写

1.上述代码执行前提,子类覆写了print方法,否则无法实现多态
2.子类没有覆写想要的方法时,编译不出错,对于子类而言,是否方法覆写是可选择的
3.如果要强制子类进行方法覆写,则父类使用abstract进行抽象,则子类必须覆写,否则出错。

6.抽象类

抽象类:普通类的超集,只是比普通类多了一些抽象方法。java 中用abstract定义抽象类和抽象方法。

普通类写法:

public  class Sharp {
    public void print(){  }
}

抽象类写法:

Sharp类是一个抽象类,print方法是一个抽象方法。抽象方法一定在抽象类里。抽象方法只有声明,没有方法体{}

public  abstract class Sharp {
    public abstract void print();
}

重点:

1.抽象方法无法直接实例化对象 Sharp sharp=new Sharp() 错
2.子类继承抽象类,子类必须覆写所有抽象方法(普通子类),若子类也为抽象类,则子类可选择是否覆写父类抽象方法。
3.抽象类仍然可以有构造类,普通方法等(普通类有的,抽象类也有)。子类仍然遵循对象的实例化流程,先调用父类构造
4.抽象类仍然是单继承局限,一个类只能继承一个类

问:
final 和 abstract 能否同时出现?
private 和 abstract 能否同时出现?
答:都不能

final 不能有子类,抽象类必须有子类
private 当前类的内部可见,子类无法覆写。抽象方法必须覆写。

抽象类的意义:强制子类覆写抽象方法,保证多态的正确运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值