目录
一、了解多态
多态即多种形态,就是同一个行为当由不同的对象去完成时产生不同的状态。
二、实现多态
在继承中实现多态:
- 完成向上转型
- 完成方法的重写
-
重写
下面我们借助动物类来理解如何实现多态:
class Animal{
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void eat(){
System.out.println(name +"正在吃饭!");
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void bark(){
System.out.println(getName()+"汪汪汪!");
}
}
class Bird extends Animal{
public Bird(String name, int age) {
super(name, age);
}
public void fly(){
System.out.println(getName()+"正在飞!");
}
}
public class Test1 {
public static void main(String[] args) {
Bird bird = new Bird("麻雀",2);
bird.fly();
bird.eat();
}
}
❀ 这是我们正常的实例化对象,实例化一个鸟类,就可以访问鸟类和其父类的方法。
public class Test1 {
public static void main(String[] args) {
Animal Animal = new Bird("麻雀",2);
animal.eat();
//不能调用了出错
//animal.fly();
}
- 这时就是完成了向上转型,用父类引用引用了一个鸟类的对象,因为鸟就是动物,所以可以发生向上转型;但是此时不能调用子类的方法和属性,因为它是一个Animal类型的,只能调用Animal这个类的方法。
但是当我们在子类写一个与父类eat()方法相同的方法,就构成了重写,这时调用eat()运行的是子类的eat()方法,就发生了动态绑定。
重写的条件:
- 方法的返回值相同(子类的返回值和父类的返回值是父子类关系也行【协变】)
- 方法的方法名相同
- 方法的参数列表相同(个数,类型,顺序)
- provated修饰的方法不能被重写
- static修饰不能被重新
- 子类的访问修饰限定符一定要大于或者等于父类的访问限定修饰符
重写的设计原则:
- 对于已经使用的类,尽量不进行修改,最好重新定义一个新的类,来重复利用其中的共性的内容,并且添加或者改动新的内容。
-
动态绑定
动态绑定:
程序在编译的时候,还是调用父类自己的方法,,但是在运行的时候,程序就会发生动态绑定(运行时绑定)——》调用子类自己的方法。
-
静态绑定
静态绑定:
也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载
public class Test1 {
public static void test(){
}
public static void test(int num){
}
public static void main(String[] args) {
test();
test(10);
}
}
-
向上转型
第一种(直接赋值):
第二种(方法的传参):
第三种(方法的返回值):
-
向下转型(不安全)
向下转型:
将一个子类对象经过向上转型之后当成父类方法使用,就不能调用子类的方法,但有时候可能需要子类特有的方法,这时:将父类引用再还原为子类对象即可。
class Animal{
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
}
class Bird extends Animal{
public Bird(String name, int age) {
super(name, age);
}
public void fly(){
System.out.println(getName()+"正在飞!");
}
public void eat(){
System.out.println(getName()+"吃鸟粮");
}
}
public class Test1 {
public static void main(String[] args) {
Animal animal = new Bird("麻雀",2);
Bird bird = (Bird) animal;//向下转型
bird.fly();
}
}
当我们向下转型一个狗类时,让他调用fly()方法,此时代码没有报错,但是当代码运行起来时,出现了报错(狗是不会飞的):
Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换:
注:
在父类的构造方法中不能调用自己的方法,因为这里也会发生动态绑定,而且此时子类对象还没构造完成可能会出现一些隐藏但是又及其难以发现的问题。
-
多态的优缺点
优点:
- 降低了代码的“圈复杂度”(if else出现的次数),避免使用大量的" if else "。
- 可拓展能力更高
缺点:
- 代码运行效率降低