Java面向对象:多态——基于继承的向上转型、方法重写、动态绑定

========================================================================================

1.多态的概念

  • 多态:是面向对象程序设计重要特性之一;
  • 多态:就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态。
  • 多态的实现:必须在继承体系之下;子类对父类的方法进行重写;通过父类的引用调用子类重写的方法;
  • 在代码运行时,当传递不同类对象时,会调用对应类中的方法。

2.向上转型和向下转型

(1)向上转型

  • 子类对象是一个父类对象,即可以将一个子类对象当成父类对象来应用。因此:向上转型是安全的,因为是从小范围向大范围的转换。
    在这里插入图片描述

例:

—父类 People

package polymorphic;

public class People {
    //父类成员变量
    public String name;
    public int age;
    //构造方法
    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //父类成员方法
    public void introduce(){
        System.out.println(name+"今年"+age+"岁了!");
    }
}

—子类Teacher

package polymorphic;


public class Teacher extends People{
    //子类新增成员属性
    public String teach;
    //子类构造方法,必须第一行使用关键字super显示调用父类构造方法
    public Teacher(String name,int age,String teach) {
        super(name,age);
        this.teach = teach;
    }
    //方法重写
    @Override
    public void introduce(){
        System.out.println(name+"是一个"+teach+"老师,今年"+age+"岁!");
    }
}

—第一种 向上转型方式:通过直接赋值 父类 实例名=(父类)子类对象;

package polymorphic;

public class Main {
    public static void main(String[] args) {
        Teacher teacher=new Teacher("于帆",48,"计算机网络");
        //显示转换 子类实例 向上转型为 父类实例
        People people=(People) teacher;
        people.introduce();
    }
}

—第二种 向上转型方式:通过方法传参,将实参(子类的对象)传给方法的形参(父类的一个引用)

package polymorphic;

public class Main {
    public static void main(String[] args) {
        Teacher teacher=new Teacher("于帆",48,"计算机网络");
        introduce((teacher));
    }
    public static void introduce(People people){
        people.introduce();
    }
}

—第三种 向上转型方式:通过方法返回 进行子类向父类的向上的转化

package polymorphic;

/**
 * @Author: 19261
 * @Date: 2021/9/12 12:21
 */
public class Main {
    public static void main(String[] args) {
        Teacher teacher=new Teacher("于帆",48,"计算机网络");
        People people=transform(teacher);
        people.introduce();
    }
    public static People transform(Teacher teacher){
        return teacher;
    }
}
  • 向上转型的优点:让代码实现更简单灵活。
  • 向上转型的缺陷:不能调用到子类特有的方法。

(2)向下转型

  • 向下转型:在实现多态时,有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象,即为向下转换。
    在这里插入图片描述
    例:
package polymorphic;

public class Student extends People{
	//子类新增成员变量
    public String grade;
    public int classNum;
    public int score;

    public Student(String name, int age, String grade, int classNum, int score) {
        super(name, age);
        this.grade = grade;
        this.classNum = classNum;
        this.score = score;
    }

    @Override
    public void introduce(){
        System.out.println(name+",今年"+grade+age+"岁,目前在"+classNum+"班!");
    }
    //子类Student新增方法
    public void showScore(){
        System.out.println(name+"总分为:"+score);
    }
}

—向下转型:为了更安全=> 在实现多态时,将向上转型的父类 再转化为 子类,以便调用子类特有方法;

package polymorphic;

public class Main {
    public static void main(String[] args) {
        Student student=new Student("张三",16,"高一",1,490);
        //向上转型
        People people=(People) student;
        people.introduce();
        //向下转型
        student=(Student) people;
        student.showScore();
    }
}

在这里插入图片描述

3.方法重写

  • 方法重写:子类继承父类之后,对于父类发方法进行重写,是一种避免修改的覆盖;
  • 重写的要求:
    • 参数列表与被重写方法的参数列表必须完全相同。
    • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
    • 父类的成员方法只能被它的子类重写。声明为 final 的方法不能被重写。声明为 static 的方法不能被重写,但是能够被再次声明。构造方法不能被重写。
    • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
    • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
    • 如果不能继承一个类,则不能重写该类的方法。
    • 重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 就会编译报错, 提示无法构成重写.
      在这里插入图片描述

4.动态绑定与静态绑定

  • 静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。
  • 动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。
  • // 对于动态绑定:就是在实现多态时,不断有向上转化或向下转化,并且父类与子类的方法可能存在重写;所以运行时,在具体调用方法时才能通过动态绑定父类或者子类实例/对象进行选择调用,明确调用的是父类方法还是子类重写的方法;
  • 避免在构造方法中调用重写的方法;“用尽量简单的方式使对象进入可工作状态”, 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题.

例:

package polymorphic;
// 父类
public class People {
    public String name;
    public int age;

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void introduce(){
        System.out.println(name+"今年"+age+"岁了!");
    }
}

// 子类
public class Student extends People{
    public String grade;
    public int classNum;
    public int score;

    public Student(String name, int age, String grade, int classNum, int score) {
        super(name, age);
        this.grade = grade;
        this.classNum = classNum;
        this.score = score;
    }

    @Override
    public void introduce(){
        System.out.println(name+",今年"+grade+age+"岁,目前在"+classNum+"班!");
    }

    public void showScore(){
        System.out.println(name+"总分为:"+score);
    }
}

public class Main {
    public static void main(String[] args) {
        Teacher teacher=new Teacher("赵六",45,"数值分析",7000);
        People people=(People) teacher;
        teacher=(Teacher) people;
        people=(People) teacher;
        teacher=(Teacher) people;
        teacher.showWages();
        people=(People) teacher;
        teacher=(Teacher) people;
        people=(People) teacher;
        people.introduce();
    }

5.多态的优缺点

缺点:代码运行效率随着多态的实现降低;

优点:

  • 类调用者对类的使用成本进一步降低;
    • 封装是让类的调用者不需要知道类的实现细节.
    • 多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可.
  • **能够降低代码的 “圈复杂度”, 避免使用大量的 if - else;**可通过创建一个相关继承关系类的数组;进行选择或者循环调用类方法或实现特定操作;
  • 可扩展能力更强;只需要创建一个新类的实例,调用重写的方法即可实现更多功能的修改;
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值