前言
在上一篇文章中,我们学会了继承,简单来说就是对共性的抽取以实现代码的复用,提高代码的效率。而今天我们就要学习一个与继承息息相关的知识点—>多态,从字面意思来理解,多态是拥有多种形态。具体来说是当我们完成一个行为时,不同的对象去完成这个行为会发生不同的状态
多态是什么?
例如:我们在生活中经常用到的打印机,打印机的主要功能其实是为了打印纸张,我们不去纠结纸张的大小,打印出来的文件有黑白,有彩色,这就是多态,同样是打印,但是打印的颜色不一样。再比如动物中的猫咪和狗狗都是需要吃饭的,但是猫咪是吃猫粮,狗狗是吃狗粮。总的来说就是:同一件事,发生在不同的对象身上,产生的效果就是不一样的。
如何实现多态
我们大概已经知道了什么是多态,但是应该如何实现多态呢?🤔换句话说,实现多态应该具备哪些条件呢?我们一个一个来解决。
实现多态必须满足以下几个条件:
1.🚝继承
2.🚄重写(包含动态绑定)
3.🚅子类必须要对父类中方法进行重写
4.🚈通过父类的引用调用重写的方法
继承很好理解,子类通过关键字extends继承父类,形成并在继承体系下完成,那这个向上转型该怎么理解呢?
向上转型
向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
语法格式:父类类型 对象名 = new 子类类型()
我们通过代码来看一看
/**
* @author Jason
* @date 2023/1/2 16:01
*/
class Animal{
public String name;
public int age;
public void eat(){
System.out.println(name+"吃饭");
}
}
class Dog extends Animal{
public void bark1(){
System.out.println(name+"汪汪叫");
}
}
class Cat extends Animal{
public void bark2(){
System.out.println(name+"喵喵叫");
}
}
public class Test {
public static void main(String[] args) {
Animal animal1=new Dog();//向上转型
animal1.name="坦克";
animal1.eat();
System.out.println("华丽的分割线==================");
Animal animal2=new Cat();//向上转型
animal2.name="咪咪";
animal2.eat();
}
}
向上转型一共有三种方法,第一种就是我们刚刚提到:📓直接赋值,还有方法传参以及方法返回
📔方法传参向上转型
public static void func(Animal animal){
System.out.println("方法传参向上传参");
}
public static void main(String[] args) {
Dog dog=new Dog();
func(dog);
}
📗返回值向上传参
public static Animal func2(){
System.out.println("返回值传参");
return new Dog();
}
以上就是向上转型的三种方法
那是否可以通过父类去调用子类的成员呢?我们来看看。⬇️
🎥提示:当我通过父类的引用去调用子类特有的成员方法时出现了报错,简单来说,我的父类没有bark1和bark2方法,是不能调用的(这也是向上转型的一大缺点),但好处就是能够使代码更加灵活起来。只能调用父类自己的方法,不能去调用子类特有的方法。
向上转型的优点😃:能让代码变得更加灵活
向上转型的缺点😭:不能调用子类特有的方法
代码中我们创建了一个父类为Animal,两个子类Dog和Cat继承于父类Animal。注意看注释后的两行代码,左侧为父类类型,右侧为子类对象,所以理论上来说,等号两边的数据必须一致,否则就会报错。animal虽然是父类类型但是可以引用一个子类对象,因为范围是从小范围向大范围的转换。
猫咪和狗狗都是动物,所以将子类对象转化为父类引用是完全可以的,大的范围是囊括小范围的,所以我们向上转型是安全的。
向下转型(不推荐)
我们通过向上转型将子类对象当成了父类方法使用,这个时候父类是无法再去调用子类方法的,由于某些业务需要,有的时候需要调用子类特有的方法,这个时候就可以用向下转型。
为什么不推荐使用向下转型呢?⬇️
public static