Java学习笔记二十五:Java面向对象的三大特性之多态

news/2024/7/7 20:19:44

Java面向对象的三大特性之多态

 

 

一:什么是多态;

 

多态是同一个行为具有多个不同表现形式或形态的能力.

多态就是同一个接口,使用不同的实例而执行不同操作.

多态性是对象多种表现形式的体现。

现实中,比如我们按下 F1 键这个动作:

  • 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
  • 如果当前在 Word 下弹出的就是 Word 帮助;
  • 在 Windows 下弹出的就是 Windows 帮助和支持。

同一个事件发生在不同的对象上会产生不同的结果。

二:多态的优点;

  • 1. 消除类型之间的耦合关系
  • 2. 可替换性
  • 3. 可扩充性
  • 4. 接口性
  • 5. 灵活性
  • 6. 简化性

三:多态存在的三个必要条件;

  • 继承
  • 重写
  • 父类引用指向子类对象

比如:

Parent p = new Child();

  当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

以下是一个多态实例的演示,详细说明请看注释:

Test.java 文件代码:

public class Test {public static void main(String[] args) {show(new Cat());  // 以 Cat 对象调用 show 方法show(new Dog());  // 以 Dog 对象调用 show 方法
                Animal a = new Cat();  // 向上转型  a.eat();               // 调用的是 Cat 的 eatCat c = (Cat)a;        // 向下转型  c.work();        // 调用的是 Cat 的 work
  }  public static void show(Animal a)  {a.eat();  // 类型判断if (a instanceof Cat)  {  // 猫做的事情 Cat c = (Cat)a;  c.work();  } else if (a instanceof Dog) { // 狗做的事情 Dog c = (Dog)a;  c.work();  }  }  
}abstract class Animal {  abstract void eat();  
}  class Cat extends Animal {  public void eat() {  System.out.println("吃鱼");  }  public void work() {  System.out.println("抓老鼠");  }  
}  class Dog extends Animal {  public void eat() {  System.out.println("吃骨头");  }  public void work() {  System.out.println("看家");  }  
}

运行结果为:

吃鱼
抓老鼠
吃骨头 看家 吃鱼 抓老鼠

四:虚方法;

我们将介绍在Java中,当设计类时,被重写的方法的行为怎样影响多态性。

我们已经讨论了方法的重写,也就是子类能够重写父类的方法。

当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。

要想调用父类中被重写的方法,则必须使用关键字super。

Employee.java 文件代码:

public class Employee {private String name;private String address;private int number;public Employee(String name, String address, int number) {System.out.println("Employee 构造函数");this.name = name;this.address = address;this.number = number;}public void mailCheck() {System.out.println("邮寄支票给: " + this.name+ " " + this.address);}public String toString() {return name + " " + address + " " + number;}public String getName() {return name;}public String getAddress() {return address;}public void setAddress(String newAddress) {address = newAddress;}public int getNumber() {return number;}
}

假设下面的类继承Employee类:

Salary.java 文件代码:

public class Salary extends Employee
{private double salary; // 全年工资public Salary(String name, String address, int number, double salary) {super(name, address, number);setSalary(salary);}public void mailCheck() {System.out.println("Salary 类的 mailCheck 方法 ");System.out.println("邮寄支票给:" + getName()+ " ,工资为:" + salary);}public double getSalary() {return salary;}public void setSalary(double newSalary) {if(newSalary >= 0.0) {salary = newSalary;}}public double computePay() {System.out.println("计算工资,付给:" + getName());return salary/52;}
}

现在我们仔细阅读下面的代码,尝试给出它的输出结果:

VirtualDemo.java 文件代码:

public class VirtualDemo {public static void main(String [] args) {Salary s = new Salary("员工 A", "北京", 3, 3600.00);Employee e = new Salary("员工 B", "上海", 2, 2400.00);System.out.println("使用 Salary 的引用调用 mailCheck -- ");s.mailCheck();System.out.println("\n使用 Employee 的引用调用 mailCheck--");e.mailCheck();}
}

以上实例编译运行结果如下:

Employee 构造函数
Employee 构造函数 使用 Salary 的引用调用 mailCheck -- Salary 类的 mailCheck 方法 邮寄支票给:员工 A ,工资为:3600.0 使用 Employee 的引用调用 mailCheck-- Salary 类的 mailCheck 方法 邮寄支票给:员工 B ,工资为:2400.0

例子解析

  • 实例中,实例化了两个 Salary 对象:一个使用 Salary 引用 s,另一个使用 Employee 引用 e。

  • 当调用 s.mailCheck() 时,编译器在编译时会在 Salary 类中找到 mailCheck(),执行过程 JVM 就调用 Salary 类的 mailCheck()。

  • 因为 e 是 Employee 的引用,所以调用 e 的 mailCheck() 方法时,编译器会去 Employee 类查找 mailCheck() 方法 。

  • 在编译的时候,编译器使用 Employee 类中的 mailCheck() 方法验证该语句, 但是在运行的时候,Java虚拟机(JVM)调用的是 Salary 类中的 mailCheck() 方法。

以上整个过程被称为虚拟方法调用,该方法被称为虚拟方法。

Java中所有的方法都能以这种方式表现,因此,重写的方法能在运行时调用,不管编译的时候源代码中引用变量是什么数据类型。

五:多态的实现方式;

方式一:重写:

方式二:接口

  • 1. 生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。

  • 2. java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。

方式三:抽象类和抽象方法

转载于:https://www.cnblogs.com/pureqh/p/9165085.html


http://lihuaxi.xjx100.cn/news/237944.html

相关文章

Observables简介以及它们与Promise有何不同

‘Observables’, ‘Observables’, ‘Observables’...Yes! Today, we will talk about this often discussed word of the market. Well also learn how they are different from Promises (havent heard about Promises? Not to worry! You will know more soon). Let’s s…

Android组件框架:Android组件管理者ActivityManager

关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse163.com与我交流。 第一次阅览本系列文章,请参见导读&a…

区块链推广所需的三个关键因素

想知道更多关于区块链技术知识,请百度【链客区块链技术问答社区】 链客,有问必答!在现有产业中推广区块链的3个关键 区块链的设计是为了展示无可辩驳的真理,而不是依靠权威的控制。虽然这听起来很理想,但问题是&#…

Wireshark使用教程:不同报文颜色的含义

“ Wireshark色彩规则。”在Wireshark主界面,报文会显示各种各样的颜色,它们表示不同的含义。这些颜色,是由色彩规则控制的。对这些颜色进行适当的了解,对分析报文有很大帮助。01—设置色彩规则有两个入口,一个在报文上…

区块链社交APP协议分析预告

2017年,比特币的火热,直接导致了代币市场的繁荣;2018年,作为信用体系的未来解决方案,区块链引发了互联网原住民的淘金热。作为风口上的引流神器,区块链技术与社交网络结合起来,产生了一系列区块…

使用FortJs使用现代JavaScript开发Node.js

介绍 (Introduction) Nodejs gives you the power to write server side code using JavaScript. In fact, it is very easy and fast to create a web server using Nodejs. There are several frameworks available on Node package manager which makes the development eve…

[Doctrine Migrations] 数据库迁移组件的深入解析三:自定义数据字段类型

自定义type 根据官方文档&#xff0c;新建TinyIntType类&#xff0c;集成Type&#xff0c;并重写getName&#xff0c;getSqlDeclaration&#xff0c;convertToPHPValue&#xff0c;getBindingType等方法。 TinyIntType.php完整代码&#xff1a; <?php namespace db\types; …

(转)如何修改maven的默认jdk版本

背景&#xff1a;在maven的配置文件中配置编译的jdk插件&#xff0c;就不需要在eclipse中进行重新的指定了。 问题 1、创建maven项目的时候&#xff0c;jdk版本是1.5版本&#xff0c;而自己安装的是1.7或者1.8版本。 2、每次右键项目名-maven->update project 时候&#xff…