4.4 多态

本文详细介绍了Java中的多态,包括多态的概念、实现方式(方法重载和重写)、向上转型和向下转型的示例以及instanceof关键字的应用。作者强调了多态在编程中的灵活性和代码可维护性。
摘要由CSDN通过智能技术生成

思维导图:

 4.4 多态

在深入研究对象的世界后,我们已经学到了封装和继承。接下来,我们要讨论的是面向对象编程的另一个核心概念:多态。

4.4.1 多态概述

多态是面向对象的三大特性之一,它允许我们以统一的方式处理不同类的对象。简单来说,多态允许一个接口或父类引用代表其任何派生类的对象。这意味着,我们可以设计一个方法,它的输入参数是父类类型,但当我们传递该方法的子类对象时,它会根据对象的实际类型执行相应的操作。

一个经典的例子是动物和它们的叫声。考虑一个“动物”抽象类和几个从动物类派生出来的子类,如“猫”和“狗”。虽然每种动物的叫声都是不同的,但我们可以定义一个方法,让它接受一个动物对象并让动物叫。当我们传递一个猫对象时,它会“喵喵叫”;当我们传递一个狗对象时,它会“汪汪叫”。

在Java中,多态主要体现在以下两个方面:

  1. 方法的重载:同一个方法名但参数类型或参数数量不同。
  2. 对象的多态(方法的重写):子类覆盖父类的方法。

4.4.2 多态示例

考虑以下的Java代码示例:

// 定义抽象类Animal
abstract class Animal {
    abstract void shout();
}

// 定义Cat类,继承自Animal
class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("喵喵……");
    }
}

// 定义Dog类,继承自Animal
class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("汪汪……");
    }
}

// 定义测试类
public class Example14 {
    public static void main(String[] args) {
        Animal an1 = new Cat();  // Cat对象向上转型为Animal
        Animal an2 = new Dog();  // Dog对象向上转型为Animal
        
        an1.shout();  // 输出“喵喵……”
        an2.shout();  // 输出“汪汪……”
    }
}

此代码展示了如何使用抽象类和继承来实现多态。当我们运行这个程序时,输出结果为:“喵喵……汪汪……”。

这是因为,尽管an1an2都是被声明为Animal类型的,但它们实际引用的对象是CatDog,因此当我们调用shout()方法时,它们分别执行了Cat类和Dog类中的实现。

这就是多态的魔力,允许我们编写更加通用、可扩展和可维护的代码。

4.4.2 对象类型的转换笔记


1. 对象类型转换概述

  • 向上转型: 子类对象 → 父类对象。
  • 向下转型: 父类对象 → 子类对象。

2. 对象向上转型

  • 当一个子类对象被当作父类对象使用时,就发生了向上转型。
  • 向上转型是自动完成的。

优点: - 增加程序的灵活性。 - 有助于隐藏具体的实现代码,从而更好地使用抽象类编写程序。

例子:

class Animal {
    public void shout() {
        System.out.println("喵喵……");
    }
}

class Dog extends Animal {
    public void shout() {
        System.out.println("汪汪……");
    }
    public void eat() {
        System.out.println("吃骨头……");
    }
}

public class Example15 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Animal an = dog; // 向上转型
        an.shout(); // 输出 "汪汪……"
    }
}

注意: - 一个向上转型的对象无法调用子类中特有的方法。


3. 对象向下转型

  • 使用向下转型来重新获得子类特有的属性和方法。
  • 向下转型必须明确指定转型的数据类型,并用强制类型转换符进行标识。
  • 必须先进行向上转型才能进行向下转型,否则会出现异常。

例子:

class Animal {
    public void shout() {
        System.out.println("喵喵……");
    }
}

class Dog extends Animal {
    public void shout() {
        System.out.println("汪汪……");
    }
    public void eat() {
        System.out.println("吃骨头……");
    }
}

public class Example16 {
    public static void main(String[] args) {
        Animal an = new Dog(); // 向上转型
        Dog dog = (Dog)an;    // 向下转型
        dog.shout(); // 输出 "汪汪……"
        dog.eat();   // 输出 "吃骨头……"
    }
}

注意: - 不能直接将父类实例强制转换为子类实例,这会导致错误。例如: java Dog dog = (Dog) new Animal(); // 编译错误


通过以上的解释和示例代码,我们可以明白Java中对象的向上转型和向下转型的原理及其用法。

4.4.3 instanceof关键字笔记


1. 简介

  • Java提供了instanceof关键字,用于判断一个对象是否是某个特定类或接口的实例。

语法格式:

对象 instanceof 类(或接口)
  • 如果“对象”是指定的类或接口的实例对象,则结果返回true,否则返回false

2. 示例

文件4-17 Example17.java:

class Animal {
    public void shout() {
        System.out.println("动物叫……");
    }
}

class Dog extends Animal {
    public void shout() {
        System.out.println("汪汪……");
    }
    public void eat() {
        System.out.println("吃骨头……");
    }
}

public class Example17 {
    public static void main(String[] args) {
        Animal a1 = new Dog(); // 向上转型
        System.out.println("Animal a1 = new Dog():" + (a1 instanceof Animal));
        System.out.println("Animal a1 = new Dog():" + (a1 instanceof Dog));

        Animal a2 = new Animal(); 
        System.out.println("Animal a2 = new Animal():" + (a2 instanceof Animal));
        System.out.println("Animal a2 = new Animal():" + (a2 instanceof Dog));
    }
}

输出:

Animal a1 = new Dog():true
Animal a1 = new Dog():true
Animal a2 = new Animal():true
Animal a2 = new Animal():false

3. 结论和解析

  • 当一个对象是一个类的实例或者是其子类的实例时,使用instanceof检查会返回true
  • 在上面的示例中,a1Dog类的实例,因此它既是Dog的实例又是Animal的实例。
  • a2仅仅是Animal的实例,不是Dog的实例,所以当我们检查它是否是Dog的实例时,返回false

使用instanceof关键字,我们可以在运行时判断对象的实际类型,从而做出相应的逻辑判断。这在多态的情境中尤其有用,可以让我们更加灵活地处理不同类型的对象。

4.4 多态总结


1. 重点:

  • 定义: 多态是面向对象编程的三大特性之一,允许将子类的对象当作父类的对象使用。
  • 实现: Java中的多态主要依赖于继承、接口和重写。
  • 向上转型: 当子类对象被当作父类对象使用时,会发生自动的向上转型。例如:Animal a = new Dog(); 这里,Dog对象自动转型为Animal。
  • 向下转型: 可以使用强制类型转换将父类对象转为子类对象,但在转型之前,该对象确实应该是那个特定子类的实例。例如:Dog d = (Dog) a; 这里,a必须实际上是Dog的一个实例。
  • instanceof 关键字: 可以检查一个对象是否是某个特定类或接口的实例。

2. 难点:

  • 理解: 对于初学者,理解不同对象之间的动态绑定可能是个挑战。
  • 向下转型的风险: 若试图对不正确的类型进行向下转型,会引发运行时异常。例如,若a是Cat的实例,那么(Dog) a将抛出异常。
  • 方法调用: 当使用多态时,始终会调用实际对象的重写方法,而不是引用变量的类型的方法。这意味着,对于上面的例子,如果Dog类重写了shout方法,那么a.shout()将调用Dog类的shout方法,而不是Animal类的。

3. 易错点:

  • 误解向下转型: 很多初学者可能认为,任何父类引用都可以被向下转型为任何子类,这是错误的。例如,Animal a = new Animal(); Dog d = (Dog) a; 这将导致运行时异常。
  • 丢失功能: 在向上转型后,只能调用在父类中定义的方法和属性,即使子类有更多的功能。例如,如果Dog类有一个特有的fetch方法,那么你不能使用Animal引用a来调用a.fetch()
  • 混淆方法覆盖与重载: 多态涉及到方法覆盖(子类提供父类方法的特定实现),而不是方法重载(同一个类中的方法有不同的参数)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏驰和徐策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值