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

Java-面向对象-多态和抽象类

目录

什么是多态?

多态的优点

多态存在的三个必要条件

虚函数

重写

多态的实现方式

什么是抽象类?

继承抽象类

实现抽象方法

抽象类总结


什么是多态?

多态就是一个行为具有多种不同的表现形式

举例:

我们按下 F1 键这个动作:

  • 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档

  • 如果当前在 Word 下弹出的就是 Word 帮助

  • 在 Windows 下弹出的就是 Windows 帮助和支持

多态的优点

  • 消除类型之间的耦合性
  • 灵活性(接口性)
  • 可替换性
  • 可扩充性
  • 简化性

多态存在的三个必要条件

  • 继承
  • 重写
  • 父类引用执行子类对象(核心)

演示:

class Animal {
    // 定义一个方法,让动物发出声音
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

class Dog extends Animal {
    // 覆盖父类的 makeSound 方法
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

class Cat extends Animal {
    // 覆盖父类的 makeSound 方法
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

class Bird extends Animal {
    // 覆盖父类的 makeSound 方法
    @Override
    public void makeSound() {
        System.out.println("叽叽喳喳");
    }
}

public class Zoo {
    public static void main(String[] args) {
        // 创建一个 Animal 类型的数组,用来存储不同类型的动物
        Animal[] animals = new Animal[3];

        // 将不同类型的动物对象赋值给数组
        animals[0] = new Dog();
        animals[1] = new Cat();
        animals[2] = new Bird();

        // 遍历数组,调用每个动物的 makeSound 方法
        for (Animal animal : animals) {
            animal.makeSound();
        }
    }
}

通过这个实例是想说明,多态的核心是:父类引用执行子类对象

虚函数

我们可以把这段代码想象成一个动物园管理员(Zoo 类中的 main 方法)在管理动物。管理员有一个笼子(Animal 类型的数组),笼子里可以放各种动物(DogCatBird)。管理员不需要知道笼子里具体是什么动物,只需要让每个动物发出自己的声音(调用 makeSound 方法)。 

虚函数

Java中的方法默认就是“虚函数”,即支持动态绑定(也称为动态多态)

演示:

class Menu {
    // 定义一个方法,表示品尝菜品
    public void taste() {
        System.out.println("品尝一道普通的菜品");
    }
}

class ChefA extends Menu {
    // 覆盖父类的 taste 方法
    @Override
    public void taste() {
        System.out.println("品尝一道由厨师A烹饪的美味菜品");
    }
}

class ChefB extends Menu {
    // 覆盖父类的 taste 方法
    @Override
    public void taste() {
        System.out.println("品尝一道由厨师B烹饪的特色菜品");
    }
}

public class Restaurant {
    public static void main(String[] args) {
        // 创建一个 Menu 类型的引用,指向不同的厨师烹饪的菜品
        Menu menu1 = new ChefA();
        Menu menu2 = new ChefB();

        // 顾客品尝菜品
        menu1.taste(); // 输出:品尝一道由厨师A烹饪的美味菜品
        menu2.taste(); // 输出:品尝一道由厨师B烹饪的特色菜品
    }
}

这意味着方法的调用是在运行时根据对象的实际类型来决定的,而不是根据引用的类型。这正是多态的核心所在。

重写

在Java中,当一个父类类型的引用指向一个子类对象时,调用方法时会根据对象的实际类型来决定调用哪个方法如果没有重写,子类将继承父类的方法,而不会提供自己的实现。这样,动态绑定就失去了意义,因为调用的始终是父类的方法

多态的实现方式

  • 重写/重载
  • 接口
  • 抽行类和抽象方法

什么是抽象类?

在Java中,抽象类(Abstract Class)是一种特殊的类,它不能被直接实例化,但可以作为其他类的父类。这里可能有同学问,既然抽象类都不能被实例化,那存在抽象类的意义是什么呢?

  • 抽象类的定义

抽象类是通过关键字 abstract 修饰的类,它不能被实例化,但可以包含抽象方法(没有具体实现的方法)和具体方法(有具体实现的方法)抽象方法也必须用 abstract 关键字修饰,且没有具体的方法体。

abstract class Animal {
    // 抽象方法,没有具体实现
    public abstract void makeSound();

    // 具体方法,有具体实现
    public void eat() {
        System.out.println("动物吃东西");
    }
}
  • 抽象类存在的意义

抽象类的主要作用是定义一组通用的接口和行为规范,这些规范可以被多个子类共享和实现。通过抽象类,我们可以定义一些通用的方法签名(抽象方法),而具体的实现细节则由子类提供

演示:

假设你有一个汽车工厂,工厂生产各种类型的汽车,比如轿车、卡车和摩托车。虽然这些汽车的类型不同,但它们都有共同的行为,比如“启动”和“停止”。抽象类就像汽车工厂的蓝图,定义了所有汽车必须具备的基本行为,而具体的实现则由每种汽车来完成

abstract class Vehicle {
    // 抽象方法,定义所有车辆必须具备的行为
    public abstract void start();
    public abstract void stop();
}

class Car extends Vehicle {
    @Override
    public void start() {
        System.out.println("轿车启动");
    }

    @Override
    public void stop() {
        System.out.println("轿车停止");
    }
}

class Truck extends Vehicle {
    @Override
    public void start() {
        System.out.println("卡车启动");
    }

    @Override
    public void stop() {
        System.out.println("卡车停止");
    }
}

继承抽象类

要继承抽象类,需要使用 extends 关键字。继承抽象类的子类有两种情况:

  • 子类是抽象类

子类可以不实现父类中的所有抽象方法,但子类本身也必须被声明为抽象类

abstract class Animal {
    // 抽象方法,没有具体实现
    public abstract void makeSound();

    // 具体方法,有具体实现
    public void eat() {
        System.out.println("动物吃东西");
    }
}

abstract class Mammal extends Animal {
    // 子类继承了抽象类 Animal,但没有实现 makeSound 方法
    // 因此,子类 Mammal 也必须被声明为抽象类
}
  • 子类是非抽象类

子类必须实现父类中的所有抽象方法

abstract class Animal {
    // 抽象方法,没有具体实现
    public abstract void makeSound();

    // 具体方法,有具体实现
    public void eat() {
        System.out.println("动物吃东西");
    }
}

class Dog extends Animal {
    // 实现父类中的抽象方法
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

实现抽象方法

实现抽象方法时,需要使用 @Override 注解(可选,但推荐使用)来覆盖父类的方法。

abstract class Animal {
    // 抽象方法,没有具体实现
    public abstract void makeSound();

    // 具体方法,有具体实现
    public void eat() {
        System.out.println("动物吃东西");
    }
}

class Cat extends Animal {
    // 实现父类中的抽象方法
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

一旦子类实现了父类中的所有抽象方法,就可以被实例化,并且使用:

public class Zoo {
    public static void main(String[] args) {
        // 创建 Dog 类的实例
        Dog dog = new Dog();
        dog.makeSound(); // 输出:汪汪汪
        dog.eat();       // 输出:动物吃东西

        // 创建 Cat 类的实例
        Cat cat = new Cat();
        cat.makeSound(); // 输出:喵喵喵
        cat.eat();       // 输出:动物吃东西
    }
}

抽象类总结

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

相关文章:

  • 【Lua】一文快速掌握 Lua 语言指令(Lua 备忘清单)
  • 5分钟快速了解自动化测试
  • 【AI News | 20250327】每日AI进展
  • 本地ping虚拟机win10的地址
  • 【解决】:VSCode 中识别不到电脑中的已安装的 Git
  • 多模态大模型训练范式演进与前瞻
  • 算法解题有感
  • Python 简单的用户权限判断
  • 使用QuickReporter将多张图片插入在word多行的表格中
  • R语言对偏态换数据进行转换(对数、平方根、立方根)
  • MFC添加免费版大漠3.1233
  • AI编程工具哪家强?对比Cusor、Copilot、Cline
  • 中医病因辨证
  • Unity Shader 学习18:Shader书写基本功整理
  • 一款超级好用且开源免费的数据可视化工具——Superset
  • Postman下载安装使用指南
  • Vue 3 + Composition API + Vite + Pinia + Element Plus 构建项目的完整指南
  • vue复习1~45
  • 数据安全与网络安全——问答复习
  • STL入门
  • 网站建设的常见问题/免费注册个人网站
  • wap网站为什么没有了/图片优化是什么意思
  • 网站做3年/西安优化外
  • 建设网站能赚钱/关键词seo优化
  • 上海加盟网网站建设/模板建站平台
  • 网站开发与推广方向/最新国内重大新闻