什么是继承,向上下转型,多态?

本文解析了Java中的继承概念,如何解决代码重复问题,以及单继承限制的原因。通过实例展示了子类的创建、重写、向上转型和向下转型,讲解了多态的定义、条件及其实现。深入探讨了继承与多态在实际编程中的应用和优势。

简介

继承?向上下转型?多态?,都是什么鬼,其实三者是有联系的,终于理解清楚了

什么是继承

继承是用来表示类之间的 is-a 关系:狗是动物,电脑是机器

继承的分类

1.单继承

2.多继承

​ 一个子类可以继承多个父类,比如猫即使猫科动物,也是哺乳动物

Java是支持单继承的

继承解决了什么问题?

假如两个类有一些相同的属性和方法,我们就可以将这些相同的部分,抽取到父类中,让两个子类继承父类。

这样,两个子类就可以重用父类中的代码,避免代码重复写多遍

1.减少重复代码

2.从设计的角度来说,也有一种结构美感(艺术感)

​ 人类认知的角度上来说,是一种 is-a 关系。我们通过继承来关联两个类,反应真实世界中的这种关系,非常符合人类的认知

继承的缺点

过度使用继承,继承层次过深过复杂,就会导致代码可读性、可维护性变差。
为了了解一个类的功能,我们不仅需要查看这个类的代码,还需要按照继承关系一层一层地往上查看“父类、父类的父类……”的代码。
还有,子类和父类高度耦合,修改父类的代码,会直接影响到子类

为什么Java只支持单继承

为什么类是单继承的?如果类是多继承的,且两个父类中都实现了init()方法,

子类在调用时存在调用的不确定性(不知道调用哪个类的init()方法)。

继承的代码探索

上面都是里面,下面是实战,根据代码来探索Java 继承的特性

父类: Animal

package p2.code.obj.lab_05_03.extendHello;

import p2.code.obj.lab_05_02.Main;

/**
 * @Author: wuyuhong
 * @Date: 2021/11/26 - 11 - 26 - 9:16 下午
 * @Description: p2.code.obj.lab_05_03.extendHello
 * @Version: 1.0
 */
public class Animal {
    public String name="动物";
    public boolean canRun;
    public Animal(){
        System.out.println("父类-->构造方法执行");
    }
    public Animal(boolean canRun){
        this.canRun=canRun;
        System.out.println("父类-->有参构造执行");
    }
    public void sayHi(){
        System.out.println("Animal Hi");
    }
    private void sayHello(){
        System.out.println("Animal hello");
    }
    public void sayOMG(){
        System.out.println("Animal Oh MY GOD");
    }

    public static void main(String[] args) {
        Animal animal=new Animal();
        animal.sayHello(); // 私有方法只能在类内部能访问
    }
}

子类:

package p2.code.obj.lab_05_03.extendHello;

/**
 * @Author: wuyuhong
 * @Date: 2021/11/26 - 11 - 26 - 9:17 下午
 * @Description: p2.code.obj.lab_05_03.extendHello
 * @Version: 1.0
 */
public class Dog extends Animal{
    private String name = "dog"; // 当父类属性和子类属性相同时,当子类被调用,会使用子类自己的属性
    // public String name = "小狗";

    public Dog() {
        // 不写super(); 当创建Dog对象时,默认会执行父类构造函数
        // super();    // 只能执行一个父类构造函数,不能即执行super(),又执行super(true);
        super(true);
    }
    public void helloFunc(){
        super.sayHi(); // 可以使用super调用父类方法,假设sayHi被重写,则可以使用super这种方式来调用父类的方法
        System.out.println(super.name); // 可以是使用super的方式访问父类属性。假设父类属性被重写
        // 也可以修改父类的属性
        super.name="Animal";
    }

    @Override
    public void sayOMG() {
        System.out.println("wang~ oh my god");
    }


    private void sayYYDS(){
        System.out.println("yyds");
    }

    public static void main(String[] args) {
        Dog dog=new Dog();
        System.out.println(dog.name);
        dog.helloFunc();
        dog.sayHi(); // 可以直接调用父类的方法(前提是父类的方法是public 或protected),
        dog.sayOMG(); // 假设sayHi被重写,那么子类调用自身被重写的方法

       

    }
   


}

子类的创建
 public Dog() {
        // 不写super(); 当创建Dog对象时,默认会执行父类构造函数
        // super();    // 只能执行一个父类构造函数,不能即执行super(),又执行super(true);
        super(true);
 }

当创建Dog对象时,默认会执行父类构造函数,然后拥有父类公开的属性

只能执行一个父类构造函数,不能即执行super(),又执行super(true);

super关键字
   public void helloFunc(){
        super.sayHi(); // 可以使用super调用父类方法,假设sayHi被重写,则可以使用super这种方式来调用父类的方法
        System.out.println(super.name); // 可以是使用super的方式访问父类属性。假设父类属性被重写
        // 也可以修改父类的属性
        super.name="Animal";
    }

super.sayHi(); 可以使用super调用父类方法,假设sayHi被重写,则可以使用super这种方式来调用父类的方法

System.out.println(super.name); 可以是使用super的方式访问父类属性。假设父类属性被重写

super.name=“Animal”; 可以修改父类的属性

子类的重写

重写属性:

 private String name = "dog"; // 当父类属性和子类属性相同时,当子类被调用,会使用子类自己的属性
    // public String name = "小狗";

重写方法

  @Override
    public void sayOMG() {
        System.out.println("wang~ oh my god");
    }
创建子类对象时,JVM创建了几个对象

即然子类被创建会调用父类的构造方法super(),那么当子类被创建时,JVM创建了几个对象?
答案是一个,只是在子类构造中调用了父类的构造函数,并没有同时创建父类对象

怎么验证呢?可以看字节码指令来验证

在这里插入图片描述

子类创建后的使用
 Dog dog=new Dog();
 System.out.println(dog.name);
        dog.helloFunc();
        dog.sayHi(); // 可以直接调用父类的方法(前提是父类的方法是public 或protected),
        dog.sayOMG(); // 假设sayHi被重写,那么子类调用自身被重写的方法

​ dog.sayHi(); // 可以直接调用父类的方法(前提是父类的方法是public 或protected),

​ dog.sayOMG(); // 假设sayHi被重写,那么子类调用自身被重写的方法

向上、向下转型

// 向上转型: 子类对象转化为父类对象 向上转型是多态的基础

Animal bigDog=new Dog();
System.out.println(bigDog.canRun);

bigDog.helloFunc(); 虽然helloFunc是public的,但是向上转型后还是不能访问

总结: 因此向上转型后,对象bigDog 只能访问父类和子类公共的方法和属性

// 向下转型:父类对象转化为子类对象

​ 安全的向下转型 :父类引用指向子类对象

        
        Animal dog1=new Dog();
        Dog animal1=(Dog) dog1;
        animal1.sayHi();

// 不安全的向下转型

      Animal animal2=new Animal();
        //Dog dog2=(Dog)animal2;
        // 编译无错,运行时报错 Exception in thread "main" java.lang.ClassCastException:
    
// 这样编译就不会报错
    if(animal2 instanceof Dog){
        Dog dog2=(Dog)animal2;
        System.out.println("running ?");
        dog2.sayOMG();
    }

多态

多态的定义是什么

子类可以替换父类

为什么子类能替换父类?

​ 因为子类替换父类后,其实就是向上转型,取得是子类和父类的公共部分的交集

多态的条件

1.父类可以引用子类对象(父类其实引用的是子类和父类公共的部分,包括父类的方法)

2.子类重写父类的方法

package p2.code.obj.lab_05_03.extendHello;

import java.util.Date;

/**
 * @Author: wuyuhong
 * @Date: 2021/11/27 - 11 - 27 - 2:30 下午
 * @Description: p2.code.obj.lab_05_03.extendHello
 * @Version: 1.0
 */
public class SoundCollector {

    public void say(Animal animal){
    animal.sayOMG();
    }

    public static void main(String[] args) {
     Animal dog=new Dog();
     Animal cat=new Cat();

     SoundCollector soundCollector=new SoundCollector();
     soundCollector.say(dog);
     soundCollector.say(cat);

     Dog dog1=new Dog();
     soundCollector.say(dog1);

    }
}

多态的好处

多态特性能提高代码的可扩展性和复用性

表示一类事物借助子类可以替换父类和子类可以重写父类方法的特性,所以作为封装方可以进行统一处理

​ for example: public void say(Animal animal)

既然子类可以替换父类(向上转型)
那么封装的方法say(Animal animal)就可以接收父类,来动态调用子类的方法

举个栗子:
say(Animal animal) 这个函数就像是面包机,你往say(Animal animal)中放水果,它就产出水果面包,
放肉松就产出肉松面包,放入的所有物品都是Food,Food为父类,你不可能放一个刀进去吧 哈哈哈

<think>我们正在讨论面向对象编程中的多态概念。根据用户的问题,他想理解多态的定义作用。结合之前的引用内容,我们可以从以下几个方面来阐述:1.**多态的定义**:多态(Polymorphism)是面向对象编程的三大特性之一(另外两个是封装继承)。它指的是同一个行为具有多个不同表现形式或形态的能力。简单来说,就是使用相同的接口来表示不同的实现。2.**多态的类型**:根据引用[1],多态分为编译时多态运行时多态。-**编译时多态**:也称为静态多态,通过函数重载运算符重载实现。在编译时就能确定调用哪个函数。-**运行时多态**:也称为动态多态,通过虚函数(在C++中)或方法重写(在Java中)实现,具体调用的函数在运行时根据对象的实际类型确定。3.**多态的作用**:-**增强代码的可扩展性可维护性**:通过多态,我们可以编写出更通用的代码,这些代码可以处理多种不同类型的对象,只要这些对象都继承自同一个基类或实现了同一个接口。这样,当需要添加新的类型时,不需要修改现有的通用代码,只需添加新的子类即可(开闭原则)。-**实现接口重用**:多态允许我们使用基类的接口来操作不同的子类对象,这样我们可以编写出更抽象的代码。-**解耦**:多态降低了代码之间的耦合度,因为高层模块不依赖于具体的低层模块,而是依赖于抽象。4.**多态的实现条件**(以运行时多态为例):-**继承**:必须存在继承关系的类(父类子类)。-**重写**:子类必须重写父类的方法(在C++中通过虚函数,在Java中通过方法重写)。-**向上转型**:用父类的引用指向子类的对象(这样通过父类的引用调用方法时,实际执行的是子类的方法)。5.**示例**:-引用[2]中的C++示例:基类`Animal`有纯虚析构函数(使其成为抽象类),子类`Dog`实现了析构函数。通过`Animal`指针指向`Dog`对象,在删除指针时,会调用`Dog`的析构函数(多态行为)。-引用[3]中的Java示例:同样通过继承、重写向上转型实现多态。6.**多态在代码中的体现**:-方法的多态:同一个方法在不同的子类中有不同的实现。-对象的多态:一个对象可以被看作是其自身类型,也可以被看作是其父类类型。现在,我们可以组织答案了。注意,用户要求用中文回答,并且要生成相关问题。同时,我们引用了站内引用,需要在回答中自然地添加引用标识。由于用户的问题是关于多态的定义作用,我们将重点放在这两方面,并适当举例说明。最后,按照要求生成相关问题。</think>### 面向对象编程中的多态概念解析 #### 一、多态的定义 多态(Polymorphism)是面向对象编程的三大核心特性之一(与封装、继承并列),指**同一操作作用于不同的对象时,可以产生不同的执行结果**。简言之,多态允许使用**相同接口**处理**不同类型的对象**,实现"一个接口,多种实现"的效果[^1][^3]。 #### 二、多态的实现形式 | 类型 | 实现机制 | 特点 | 示例语言 | |--------------|--------------------------|--------------------------|------------| | **编译时多态** | 函数重载/运算符重载 | 编译期确定调用版本 | C++ | | **运行时多态** | 虚函数/接口实现/方法重写 | 运行期根据对象类型确定 | C++/Java | #### 三、多态的核心作用 1. **增强代码扩展性** 新增子类无需修改现有代码[^1] ```cpp // C++示例:动物叫声多态 class Animal { public: virtual void sound() const = 0; // 纯虚函数 }; class Cat : public Animal { void sound() const override { cout << "Meow"; } // 重写实现 }; class Dog : public Animal { void sound() const override { cout << "Woof"; } // 不同实现 }; ``` 2. **实现接口统一** 不同对象通过相同接口调用[^3] ```java // Java示例:几何图形计算 Shape s = new Circle(); s.area(); // 调用Circle的面积计算 s = new Square(); s.area(); // 调用Square的面积计算 ``` 3. **降低耦合度** 调用方只需关注接口,不依赖具体实现类[^4] ```mermaid graph LR A[客户端代码] --> B[抽象接口] B --> C[具体实现类1] B --> D[具体实现类2] ``` 4. **支持反向控制(Hollywood原则)** "不要调用我们,我们会调用你" - 框架通过多态回调用户代码[^3] #### 四、多态的实现条件 1. **继承关系**:存在父子类层次结构[^3] 2. **方法重写**:子类覆盖父类方法(C++虚函数/Java重写) 3. **向上转型**:父类引用指向子类对象[^3] ```cpp Animal* animal = new Cat(); // 向上转型 animal->sound(); // 实际调用Cat::sound() ``` #### 五、经典应用场景 1. **插件系统架构** 通过接口扩展功能而不修改主程序 2. **GUI事件处理** 同一点击事件对不同控件产生不同响应 3. **游戏角色行为** 同一"攻击"指令,战士/法师执行不同动作 4. **数据库访问层** 统一接口支持MySQL/Oracle等不同驱动 > **多态的本质**:将"做什么"(接口)"怎么做"(实现)分离,使系统获得动态扩展能力[^1][^4]。如同水的不同形态(冰/水蒸气),同一接口在不同上下文中展现不同行为[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值