多态的概念
多态(Polymorphism) 是面向对象编程的三大特性之一(另外两个是封装和继承),它允许不同的对象对同一消息做出响应。多态是指同一个方法在不同的类上可以有不同的表现形式。
简单来说,就是同一个行为,在不同对象去完成时会有不同的表现形态.
例如:同一张图片去打印,黑白打印机打印出来是黑白的,彩色打印机打印出来是彩色的:
多态的实现条件
在Java中要想实现多态,主要依赖于以下因素:
- 继承:必须在继承体系下
- 方法重写:子类对父类方法进行重写
- 方法调用时对象的实际类型:在运行时,Java会根据调用方法时对象的实际类型来决定调用哪个类的方法,这被称为动态绑定
要想弄懂多态,我们得先了解重写和向上转型
重写
在Java中,重写是面向对象编程中一个重要的概念,它指的是子类提供与父类相同方法名称、相同参数列表的方法,以覆盖父类中的同名方法。重写的方法在子类中必须有与父类方法相同的签名(方法名、参数列表和返回类型),但可以有不同的实现。
重写的规则:
- 方法名相同:子类中的方法与父类中的方法必须具有相同的名称。
- 参数列表相同:子类中的方法与父类中的方法必须具有相同的参数列表(参数类型、参数顺序和参数个数)。
- 返回类型相同或为其子类:如果父类方法的返回类型不是void,则子类方法的返回类型必须与父类方法的返回类型相同或是其子类。
- 访问权限不能更低:子类方法的访问权限(public、protected、default、private)不能低于父类方法的访问权限。但是,如果父类方法是private的,那么子类不能重写它,因为private方法对于子类是不可见的。
- 重写的方法可以使用 @Override 注解来显式指定:有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.
那为什么会设计出重写这样的功能呢?
答:在生活中,我们的产品已经投入使用后,就尽量不要把已经在使用的类进行修改,而是定义一个新的类来重复利用其中的共性,通过重写来添加或改动新的内容.
向上转型
向上转型: 其实就是new一个子类对象,把它当成父类对象使用
语法:
父类类型 对象名 = new 子类类型();
例如:
Animal animal = new Dog("旺财",...);
animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换
多态
当我们了解了重写和向上转型之后,就可以理解多态了;
我们来看一个实例:
//Animal.java
public Animai{
String name;
int age;
public Animal(name,age){
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(this.name + "正在吃东西");
}
}
//Dog.java
public Dog extends Animal{
@Override
public void eat(){
System.out.println(this.name + "正在吃狗粮");
}
}
//Test.java
public Test{
pubic static void main(String args[]){
Animal animal = new Dog("旺财",2);
animal.eat();
}
}
在这个例子中,我们用向上转型,将Dog类型的对象animal转成Animal类型,在执行eat方法时由于子类Dog重写了父类Animal的方法eat,所以当animal对象调用eat方法时,会调用子类的eat方法打印出: 旺财正在吃狗粮
同样的道理,如果继续添加新的类型比如:
//Cat.java
public Cat extends Animal{
public void eat(){
System.out.println(this.name + "正在吃猫粮");
}
}
//Test.java
public Test{
pubic static void main(String args[]){
Animal animal = new Dog("旺财",2);
animal.eat();
Animal animal2 = new Cat("小咪",2);
animal2.eat();
}
}
就会打印出:旺财正在吃狗粮
小咪正在吃猫粮
这就实现了多态