当前位置: 首页 > article >正文

初识JAVA-面向对象的三大特征之多态

1. 重温面向对象

面向对象是一种解决问题的思想,它把计算机程序看作是各种对象组合起来的。每个对象都有自己的数据(属性)和行为(方法),主要依靠对象之间的交互来解决和实现问题。Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。

2. 多态

2.1 多态的概念

多态,简单来说就是多种形态,复杂点说就是不同对象去完成某个行为时产生不同的状态。

总的来说:同一件事情,发生在不同对象上,就会产生不同的结果。

2.2 多态实现条件

Java中实现多态,必须满足以下的条件,缺一不可:

1. 必须在继承的体系下才可以实现多态

2. 子类必须要对父类方法机械能重写

3. 通过父类的引用调用重写的方法

父类:

public class Pet{
    String name;
    String species;

    public Pet(String name, String species) {
        this.name = name;
        this.species = species;
    }
    public void eat(){
        System.out.println(name+"在进食");
    }
}

子类:

public class Cat extends Pet{
    public Cat(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃冻干");
    }
}
public class Dog extends Pet{
    public Dog(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃狗粮");
    }
}

进行测试:

public class TestPet {
    public static void eat(Pet pet){
        pet.eat();
    }
    public static void main(String[] args) {
        Cat cat=new Cat("咪咪","猫科动物");
        Dog dog=new Dog("旺旺","犬科动物");
        eat(cat);
        eat(dog);
    }
}

TestPet的代码时类调用者的编写

当类的调用者在编写eat这个方法时,参数类型为Pet(父类),此时在该类方法内部并不知道,也不关注当前的pet引用指向的那个子类的实例,pet这个引用调用的eat方法就可能有多种不同的表现(和pet引用的实例相关),这种行为就成为多态。

2.3 重写

重写(Override):也称为覆盖。重写是子类对父类非静态,非private修饰,非fianl修饰,非构造方法等的实现过程进行重新编写,返回值和形参都不能改变(外表不变,内心改变)。重写的好处在于子类可以根据需要,定义特定于自己的行为。

方法重写的规则:

1. 子类在重写父类方法时,必须与父类方法的方法名,参数列表要完全一致

2. 被重写的方法返回值类型可以不同,但是必须是具有父子关系的

3. 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为protected

4. 父类被static,private修饰的方法,构造函数都不能被重写

5. 重写的方法,可以使用@Override注解来显式指定

2.4 重写和重载的区别

方法重载是一个类的多态性表现,而方法重写式子类与父类的一种多态性表现

2.5 向上转型和向下转型

向上转型:实际就是创建一个子类对象,将其当作父类对象来使用

语法格式:父类类型 对象名=new 子类对象( )

Pet pet=new Dog("汪汪","犬科动物")

Pet是父类类型,但是可以引用一个子类对象,因为是从小范围到大范围的转换。

 使用场景:

1. 直接赋值

2. 方法传参

3. 方法返回

public class TestPet {
    //2.方法传参:形参为父类类型,可以接收子类对象
    public static void eat(Pet pet){
        pet.eat();
    }
    //3.作为返回值:返回任意子类对象
    public static Pet buyPet(String species){
        if("犬科动物".equals(species)){
            return new Dog("汪汪","犬科动物");
        }else if("猫科动物".equals(species)){
            return new Cat("咪咪","猫科动物");
        }else {
            return null;
        }
    }
    public static void main(String[] args) {
        //1.直接赋值:子类对象赋值给父类对象
        Pet cat=new Cat("咪咪","猫科动物");
        Pet dog=new Dog("旺旺","犬科动物");

        eat(cat);
        eat(dog);

        Pet pet=buyPet("犬科动物");
        pet.eat();

    }
}

向上转型的优点:让代码实现更加灵活

向上转型的缺点:不能调用子类特有的方法

将一个子类对象经过向上转型后当成父类方法使用,再也无法调用子类特有的方法,但有时候可能需要子类特有的方法,此时我们引入了向下转型。

向下转型:将父类引用还原成子类对象。

向下转型存在不安全的特点,例如下述代码:

public class Pet{
    String name;
    String species;

    public Pet(String name, String species) {
        this.name = name;
        this.species = species;
    }
    public void eat(){
        System.out.println(name+"在进食");
    }

}
public class Dog extends Pet{
    public Dog(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃狗粮");
    }
    public void bark(){
        System.out.println("汪汪汪!");
    }
}
public class Cat extends Pet{
    public Cat(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃冻干");
    }
    public void mew(){
        System.out.println("喵喵喵!");
    }
}
public class TestPet {

    public static void eat(Pet pet){
        pet.eat();
    }

    public static void main(String[] args) {
        Cat cat=new Cat("咪咪","猫科动物");
        Dog dog=new Dog("旺旺","犬科动物");
        //向上转型
        Pet pet=cat;
        pet.eat();
        pet=dog;
        pet.eat();
        //此时pet指向的是dog,强制还原为cat,无法正常还原,抛出ClassCastException
        cat= (Cat) pet;
        cat.mew();

        dog=(Dog) pet;
        dog.bark();

    }
}

 向下转型是不安全的,万一转型失败,运行时就会抛出异常。Java中为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转型。

public class TestPet {

    public static void eat(Pet pet){
        pet.eat();
    }

    public static void main(String[] args) {
        Cat cat=new Cat("咪咪","猫科动物");
        Dog dog=new Dog("旺旺","犬科动物");
        //向上转型
        Pet pet=cat;
        pet.eat();
        pet=dog;
        pet.eat();
        
        if(pet instanceof Cat){
            cat= (Cat) pet;
            cat.mew();
        }

        if(pet instanceof Dog){
            dog=(Dog) pet;
            dog.bark();
        }
    }
}

2.6 多态的优缺点

多态的好处

1. 能够降低代码的圈复杂度,避免使用大量的if-else语句

圈复杂度是一种描述代码复杂程度的方式,一段代码平铺直叙,那么比较简单理解,如果有很多分支条件或者循环语句,就认为理解起来复杂。

2. 可拓展能力强

如果要新增一种行为,使用多态的方式代码改动的成本就比较低

多态的缺点:

1. 属性没有多态性

当父类和子类都有同名的属性时,通过弗雷德引用,只能引用父类自己的成员属性

2.构造方法没有多态性


http://www.kler.cn/a/503863.html

相关文章:

  • C#使用OpenTK绘制3D可拖动旋转图形三棱锥
  • 基于当前最前沿的前端(Vue3 + Vite + Antdv)和后台(Spring boot)实现的低代码开发平台
  • linux: 文本编辑器vim
  • centos修改/etc/resolv.conf 重启network后又恢复到原来的状态
  • 组织切片配准(切割角度校正)
  • Apache Hop从入门到精通 第二课 Apache Hop 核心概念/术语
  • DS1302模块学习笔记
  • 【gin】http方法了解,以及RESTful API与版本控制
  • [IGP]ospf ip frr 快速重路由技术
  • 认识微服务
  • 文本在屏幕上自由游动
  • 求矩阵不靠边元素之和(PTA)C语言
  • 用 Python 处理 CSV 和 Excel 文件
  • 构建云原生后端服务——以Spring Boot + Kubernetes为例
  • 《语言模型的新型推理范式:基于链式思考与强化学习的突破》
  • 量子计算:从薛定谔的猫到你的生活
  • hive知识体系
  • ubuntu22.04安装注意点
  • 力扣 全排列
  • ros2笔记-6.5 使用ros2_control驱动机器人
  • iOS 逆向学习 - Inter-Process Communication:进程间通信
  • 56_多级缓存实现
  • 【翻译】2025年华数杯国际赛数学建模题目+翻译pdf自取
  • csv. tsv文件的导入 导出功能总结C#
  • 深度剖析 GROUP BY 和 HAVING 子句:优化 SQL 查询的利器
  • 获取按图搜索淘宝商品(拍立淘)API接口用Java示例解释说明