从一个例子理解多态(附代码解释)

本文通过一个网络游戏中的角色示例,详细解释了面向对象编程中多态的概念及其优势。多态允许父类引用指向子类对象,并根据不同子类执行相应的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我来说一下多态这个名字是什么意思,多态的英文词是polymorphism,poly的意思是许多,morph的意思是形态。所以多态的意思说白了就是许多形态。那么这许多形态是指谁的形态呢,它是说不同对象有着相同轮廓,但是在执行的时候会表现出多种的姿态。用我的例子来说,网络游戏中的诸多角色,如法师和战士。他们的类中都应该有一个跑的方法,但是跑起来的样子却并不一样。为了解释这个问题,我下面提供了一段代码。

这个例子中有一个Ren类
public class Ren {

 private String name;
 private String sex;
 
 public void run(){
  
 }
}


MT(战士)类
public class MT extends Ren{

 @Override
 public void run() {
  System.out.print("战士跑");
 }
}

FS(法师)类
public class FS extends Ren{

 @Override
 public void run() {
  System.out.print("法师跑"); 
 }
 
 
}
 

Run类
public class Run {
 public void niPao(Ren r){
  r.run();
 }

}

Test类

public class Test {

 /**
  * @param args
  */
 public static void main(String[] args) {
  /*
   多态性是允许将父对象设置成为和一个或多个它的子对象相等的技术,
   比如Parent:=Child; 多态性使得能够利用同一类(基类)
   类型的指针来引用不同类的对象,以及根据所引用对象的不同 ,
   以不同的方式执行相同的操作.
   多态的作用:把不同的子类对象都当作父类来看,
   可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,
   以适应需求的不断变化。
   */
  MT m1=new MT();
  FS f1=new FS();
  FS f2=new FS();
  
  Run r=new Run();
  //如果是法师1
  r.niPao(f1);
  //如果是法师2
  r.niPao(f2);
  //如果是战士1;
  r.niPao(m1);

 }

}

运行Test类出现的结果是 法师跑,法师跑,战士跑。可见体现了多态性的同样的轮廓,不同种姿态的特性。

这是说明多态名字为什么这么叫,但是这样的名字有什么好处呢。好处是可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

最重要的是适应不断需求的变化,假设这个游戏随着玩的人越来越多,想要多设一个角色GJS,那么此时,我们需要做的只是加一个弓箭手类如下,而并不需要多修改别处的代码。然后我们再在Test类中测试,看会出现什么结果
public class GJS extends Ren{

 @Override
 public void run() {
  
  System.out.print("弓箭手跑");
 }
}

public class Test {

 /**
  * @param args
  */
 public static void main(String[] args) {

  MT m1=new MT();
  FS f1=new FS();
  FS f2=new FS();
  
  GJS g=new GJS();
  Run r=new Run();
  //如果是法师1
  r.niPao(f1);

  //如果是法师2
  r.niPao(f2);

  //如果是战士1;
  r.niPao(m1);
 //如果是弓箭手
  r.niPao(g);
 }

在运行的结果中我们会发现最后的一项是弓箭手的一项。

这样利用多态性,我们对这个游戏实现了一个完美的扩展,在尽量少的修改(甚至不修改)原有的代码的基础上,实现了我们要干的事情。这是一件了不起的事情。在我们慢慢做一些项目,开始一些开发的时候会发现这一个特性会改变许多事情。多态性,不亏是OOP中很重要的一个特性。(在我看来这是有了封装和继承的特性之后才有的一个特性。)

}
 

<think>好的,用户之前已经询问了关于多态实现方式和形式,现在他们想要一个具体的代码示例来演示多态。我需要确保例子能够清晰展示多态的不同形式,特别是方法重和接口多态,因为这两个是动态多态的典型。同时,可能还需要提到方法重载作为静态多态例子,不过用户可能更关注运行时多态。 首先,回顾之前的回答,用户已经得到了三种多态形式的解释,包括方法重、方法重载和接口多态。现在需要用一个具体的例子来演示这些概念。应该选择一个简单易懂的场景,比如动物发出声音,或者不同支付方式的实现,这样用户容易理解。 考虑到代码的通用性,可能使用Java语言,因为之前的例子也是Java,而且Java在面向对象编程中比较典型。需要确保代码结构清晰,注释明确,能够展示向上转型和动态绑定。 用户可能希望例子覆盖继承和接口两种方式,所以可能需要设计两个例子一个基于继承的方法重,另一个基于接口的实现。这样能全面展示多态的不同实现形式。 另外,需要注意代码的正确性,比如在Java中,方法重需要遵循访问修饰符的规则,不能缩小父类方法的访问权限,同时使用@Override注解来确保正确重。接口中的方法默认是抽象的,实现类必须重。 还需要解释代码的执行结果,说明多态如何在实际运行中起作用,比如父类引用指向子类对象时,调用方法会执行子类重后的版本。同时,可能比较如果直接使用子类对象会有什么不同,以强调向上转型的重要性。 最后,总结多态的好处,比如提高代码的可扩展性和维护性,符合开闭原则等。确保用户不仅看到代码,还能理解其背后的设计理念和应用场景。</think>以下是一个具体的多态示例,通过 **继承+方法重** 和 **接口多态** 两种形式实现: --- ### **场景描述** 假设需要设计一个图形绘制系统,支持不同图形(圆形、矩形)的面积计算和绘制操作。 --- ### **代码实现** #### **1. 基于继承的多态(方法重)** ```java // 父类:定义抽象方法 abstract class Shape { public abstract double calculateArea(); // 抽象方法,子类必须实现 public void draw() { System.out.println("绘制图形..."); } } // 子类1:圆形 class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double calculateArea() { // 重父类抽象方法 return Math.PI * radius * radius; } @Override public void draw() { // 重父类具体方法 System.out.println("绘制圆形,半径:" + radius); } } // 子类2:矩形 class Rectangle extends Shape { private double width; private double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } @Override public double calculateArea() { // 重父类抽象方法 return width * height; } @Override public void draw() { // 重父类具体方法 System.out.println("绘制矩形,宽高:" + width + "x" + height); } } // 测试类 public class Main { public static void main(String[] args) { // 向上转型:父类引用指向子类对象 Shape shape1 = new Circle(5.0); Shape shape2 = new Rectangle(4.0, 6.0); // 多态调用 printShapeInfo(shape1); // 输出圆形信息 printShapeInfo(shape2); // 输出矩形信息 } // 统一处理不同图形的多态方法 public static void printShapeInfo(Shape shape) { shape.draw(); // 动态绑定到子类的draw() System.out.println("面积:" + shape.calculateArea()); // 动态绑定到子类的calculateArea() } } ``` #### **输出结果** ``` 绘制圆形,半径:5.0 面积:78.53981633974483 绘制矩形,宽高:4.0x6.0 面积:24.0 ``` --- #### **2. 基于接口的多态** ```java // 定义接口 interface Drawable { void draw(); // 接口方法(默认public abstract) } // 实现类1:圆形 class Circle implements Drawable { private double radius; public Circle(double radius) { this.radius = radius; } @Override public void draw() { // 实现接口方法 System.out.println("绘制圆形,半径:" + radius); } } // 实现类2:矩形 class Rectangle implements Drawable { private double width; private double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } @Override public void draw() { // 实现接口方法 System.out.println("绘制矩形,宽高:" + width + "x" + height); } } // 测试类 public class Main { public static void main(String[] args) { Drawable[] shapes = { new Circle(5.0), new Rectangle(4.0, 6.0) }; // 统一调用接口方法 for (Drawable shape : shapes) { shape.draw(); // 动态绑定到具体实现类的draw() } } } ``` #### **输出结果** ``` 绘制圆形,半径:5.0 绘制矩形,宽高:4.0x6.0 ``` --- ### **多态的核心体现** 1. **向上转型** - `Shape shape = new Circle(5.0)` 或 `Drawable shape = new Rectangle(4,6)` - 父类/接口引用可以接受任何子类/实现类对象。 2. **动态绑定** - 调用 `shape.draw()` 时,JVM 根据实际对象类型(如 `Circle` 或 `Rectangle`)选择对应方法。 3. **代码扩展性** - 新增图形(如 `Triangle`)时,只需继承 `Shape` 或实现 `Drawable`,无需修改 `printShapeInfo()` 或主循环代码。 --- ### **多态的优势** - **解耦合**:调用方代码(如 `printShapeInfo()`)无需关心具体图形类型。 - **可维护性**:新增功能时只需扩展子类,符合开闭原则(对扩展开放,对修改关闭)。 - **统一管理**:可将不同子类对象存入集合(如 `List<Shape>`),批量处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yxnchinahlj

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

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

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

打赏作者

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

抵扣说明:

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

余额充值