多态性及其应用

多态性

多态—在Java中,子类的对象可以替代父类的对象使用
一个变量只能有一种确定的数据类型
一个引用类型变量可能指向(引用)多种不同类型的对象
  Person p = new Student();
  Object o = new Person();//Object类型的变量o,指向Person类型的对象
  o = new Student(); //Object类型的变量o,指向Student类型的对象

父类类型的变量可以指向子类的对象

一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法
  Student m = new Student();
  m.school = “pku”; //合法,Student类有school成员变量
  Person e = new Student();
  e.school = “pku”; //非法,Person类没有school成员变量

属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。

虚拟方法调用(Virtual Method Invocation)

正常的方法调用
  Person e = new Person();
  e.getInfo();
  Student e = new Student();
  e.getInfo();
虚拟方法调用(多态情况下)
  Person e = new Student();
  e.getInfo(); //调用Student类的getInfo()方法
编译时类型和运行时类型

编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。—— 动态绑定

多态性应用举例

方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法
public class Test {
  public void method(Person e) {
    //……
    e.getInfo();
  }
  public static void main(Stirng args[]) {
    Test t = new Test();
    Student m = new Student();
    t.method(m); //子类的对象m传送给父类类型的参数e
  }
}


Person类

  1. public class Person {
  2.  
  3. //仅在类的内部可以访问.
  4. private String email;
  5. //在同一个包内该属性可以被访问.
  6. String major;
  7. //在子类中该属性可以被访问, 且该子类可以跨包
  8. protected int salary;
  9.  
  10. //访问权限最高, 无论是否在一个包内, 无论是否是子类都可以被访问.
  11. public String name;
  12. public int age;
  13. public Date birth;
  14.  
  15. private String lover;
  16.  
  17. public Person(int i) {
  18. System.out.println("[Person's constructor...]");
  19. }
  20.  
  21. public Person() {
  22. // TODO Auto-generated constructor stub
  23. }
  24.  
  25. public String getInfo(){
  26. return "name: " + name + ", " + "age: " + age + ", " + "birth: " + birth;
  27. }
  28. }

Man类继承Person类

  1. public class Man extends Person{
  2.  
  3. public void work(){
  4. System.out.println("男人工作...");
  5. }
  6.  
  7. @Override
  8. public String getInfo() {
  9. return "Man's getInfo";
  10. }
  11. }

Woman类继承Person类

  1. public class Woman extends Person{
  2.  
  3. public void shopping(){
  4. System.out.println("女人购物...");
  5. }
  6. }

TestPerson类

  1. public class TestPerson {
  2. public static void main(String[] args) {
  3.  
  4. //多态
  5.  
  6. //1. 创建一个 Man 的实例
  7. Man m1 = new Man();
  8.  
  9. //2. 创建一个 Woman 的实例
  10. Woman w1 = new Woman();
  11.  
  12. //3. 创建一个 Person 的实例
  13. Person p1 = new Person();
  14.  
  15. /**
  16. * 多态: 在Java中,父类的引用可以指向子类的对象.
  17. * 1. 在多态情况下, 父类的实例变量不能再访问子类中添加的属性和方法
  18. * 2. 方法的调用是在运行时确定的,所以调用的是 Man 类的 getInfo() 方法。—— 动态绑定(虚拟方法法调用)
  19. * 3. 在存在父子关系(多态)的情况下, 可以把父类的引用类型强制转换为子类的引用类型. 若实际上不能进行转换则系统
  20. * 会抛出 java.lang.ClassCastException 异常.
  21. * 4. 如何避免出现 java.lang.ClassCastException 异常呢? 在转换之前可以先判断一下对象实际上是否为指定的子类类型.
  22. * 使用 instanceof 运算符. 注意, 使用 instanceof 运算符, 必须要求前面的引用指向的变量和后边的类之间存在父子关系
  23. */
  24. //需要一个人, 但来的是一个男人! OK. 因为男人一定是一个人.
  25. Person p2 = new Man();
  26. System.out.println(p2.getInfo());
  27.  
  28. //需要一个人, 但来的是一个女人! OK. 因为女人一定是一个人
  29. Person p3 = new Woman();
  30.  
  31. //在多态情况下, 可以进行强制的类型转换
  32. Man m2 = (Man) p2;
  33.  
  34. System.out.println(p3 instanceof Man);
  35. System.out.println(p3 instanceof Woman);
  36.  
  37. // System.out.println(m2 instanceof Person);
  38.  
  39. // Man m3 = (Man) p3;
  40.  
  41. //需要一个男人, 但来的是个人! NO. 因为人不一定是男人.
  42. //Man m2 = new Person();
  43.  
  44. //需要个男人, 但来的是一个女人。 NO!
  45. //Man m3 = new Woamn();
  46.  
  47. Student student = new Student();
  48. student.name = "Jerry";
  49. student.birth = new Date();
  50. student.age = 1;
  51. student.school = "atguigu";
  52.  
  53. System.out.println(student.getInfo());
  54. }
  55. }

instanceof 操作符

x instanceof A:检验x是否为类A的对象,返回值为boolean型。
要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
如果x属于类A的子类B,x instanceof A值也为true。
public class Person extends Object {…}
public class Student extends Person {…}
public class Graduate extends Person {…}

public void method1(Person e) {
  if (e instanceof Person)
    // 处理Person类及其子类对象
  if (e instanceof Student)
    //处理Student类及其子类对象
  if (e instanceof Graduate)
    //处理Graduate类及其子类对象
}

练习

建立TestInstance 类,在类中定义方法method1(Person e); 在method1中:

(1)根据e的类型调用相应类的getInfo()方法。

(2)根据e的类型执行: 如果e为Person类的对象,输出:“a person”; 如果e为Student类的对象,输出 “a student” “a person ” 如果e为Graduate类的对象,输出: “a graduated student” “a student” “a person”

  1. class Person {
  2. protected String name="person";
  3. protected int age=;
  4. public String getInfo() {
  5. return "Name: "+ name + "\n" +"age: "+ age;
  6. }
  7. }
  8. class Student extends Person {
  9. protected String school="pku";
  10. public String getInfo() {
  11. return "Name: "+ name + "\nage: "+ age + "\nschool: "+ school;
  12. }
  13. }
  14. class Graduate extends Student {
  15. public String major="IT";
  16. public String getInfo(){
  17. return "Name: "+ name + "\nage: "+ age + "\nschool: "+ school+"\nmajor:"+major;
  18. }
  19. }

对象类型转换 (Casting )

基本数据类型的Casting:
  小的数据类型可以自动转换成大的数据类型
    如long g=20; double d=12.0f
  可以把大的数据类型强制转换(casting)成小的数据类型
    如 floate f=(float)12.0 int a=(int)1200L

对Java对象的强制类型转换称为造型
  从子类到父类的类型转换可以自动进行
  从父类到子类的类型转换必须通过造型(强制类型转换)实现
  无继承关系的引用类型间的转换是非法的
  在造型前可以使用instanceof操作符测试一个对象的类型

对象类型转换举例
public class Test {
  public void method(Person e) { //设Person类中没有getschool()方法
    System.out.pritnln(e.getschool()); //非法,编译时错误

    if(e instanceof Student) {
      Student me = (Student)e; //将e强制转换为Student类型
      System.out.pritnln(me.getschool());
    }
  }

  public static void main(Stirng args[]) {
    Test t = new Test();
    Student m = new Student();
    t.method(m);
  }
}


Person类

  1. public class Person {
  2. protected String name="person";
  3. protected int age=50;
  4. public String getInfo() {
  5. return "Name: "+ name + "\n" +"age: "+ age;
  6. }
  7. }
  8. class Student extends Person {
  9. protected String school="pku";
  10. public String getInfo() {
  11. return "Name: "+ name + "\nage: "+ age
  12. + "\nschool: "+ school;
  13. }
  14.  
  15. }
  16. class Graduate extends Student{
  17. public String major="IT";
  18. public String getInfo()
  19. {
  20. return "Name: "+ name + "\nage: "+ age
  21. + "\nschool: "+ school+"\nmajor:"+major;
  22. }
  23. }

TestInstance类

  1. package com.atgugu.java.ex;
  2.  
  3. public class TestInstance {
  4.  
  5. /*
  6. 在类中定义方法method1(Person e);
  7. 在method1中:
  8. (1)根据e的类型调用相应类的getInfo()方法。
  9. (2)根据e的类型执行:
  10. 如果e为Person类的对象,输出:“a person”;
  11. 如果e为Student类的对象,输出
  12.    “a student”
  13.    “a person ”
  14. 如果e为Graduate类的对象,输出:
  15.    “a graduated student”
  16.    “a student”
  17.    “a person”
  18. */
  19.  
  20. public void method1(Person e) {
  21. String info = e.getInfo();
  22. System.out.println(info);
  23.  
  24. if(e instanceof Graduate){
  25. System.out.println("a graduated student");
  26. }
  27. if(e instanceof Student){
  28. System.out.println("a student");
  29. }
  30. if(e instanceof Person){
  31. System.out.print("a person");
  32. }
  33.  
  34. System.out.println("\n");
  35.  
  36. }
  37.  
  38. public static void main(String[] args) {
  39.  
  40. TestInstance ti = new TestInstance();
  41.  
  42. Person p1 = new Person();
  43. ti.method1(p1);
  44.  
  45. Person p2 = new Student();
  46. ti.method1(p2);
  47.  
  48. Person p3 = new Graduate();
  49. ti.method1(p3);
  50. }
  51. }

Java类的设计----多态性及其应用的更多相关文章

  1. Java类的设计----Object 类

    Object类 Object类是所有Java类的根父类如果在类的声明中未使用extends关键字指明其父类,则默认父类为Object类 public class Person { ... } 等价于: ...

  2. Java类的设计----关键字super

    关键字super 在Java类中使用super来引用父类的成分 super可用于访问父类中定义的属性 super可用于调用父类中定义的成员方法 super可用于在子类构造方法中调用父类的构造方法 su ...

  3. Java类的设计----访问控制

    访问控制 可以对Java类中定义的属性和方法进行访问控制----规定不同的保护等级: public.protected.default.private //仅在类的内部可以访问. private St ...

  4. Java类的设计----方法的重写、覆盖

    方法的重写.覆盖 在子类中可以根据需要对从父类中继承来的方法进行改造—覆盖方法(方法的重置.重写),在程序执行时,子类的方法将覆盖父类的方法. 覆盖方法必须和被覆盖方法具有相同的方法名称.参数列表和返 ...

  5. java类的设计原则

    1.内聚性 类应该描述一个单一的实体,所有的类操作应该在逻辑上相互配合,支持一个连贯性的目标.例如:学生和教职工属于不同的实体,应该定义两个类. 2.一致性 要遵循一定的设计风格和命名习惯.给类.方法 ...

  6. java类和对象的基础(笔记)

    在Java类的设计中,有时希望一个类在任何时候只能有一个实例.这时可以将该类设计为单例模式(singleton).要将一个类设计为单例模式,需要把类的构造方法的访问修饰符声明为private,然后在类 ...

  7. Java 类的热替换 —— 概念、设计与实现

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp71   Java 类的热替换 -- 概念.设计与实现 构建基于 Java ...

  8. Java SE 之 数据库操作工具类(DBUtil)设计

    JDBC创建数据库基本连接 //1.加载驱动程序 Class.forName(driveName); //2.获得数据库连接 Connection connection = DriverManager ...

  9. Java实验项目三——编程实现Person类,学生类的设计及其继承关系

    Program: 编程实现Person类,学生类的设计及其继承关系 代码如下: 定义抽象类Person 1 /* 2 * Description:建立抽象类 3 * 4 * Written By:Ca ...

随机推荐

  1. 用C++画光(三)——色散

    写在前面 源码:https://github.com/bajdcc/GameFramework/blob/master/CCGameFramework/base/pe2d/Render2DScene5 ...

  2. QT 4.8 静态库编译方法

    最最初踏上QT之路是受到了XiaomaGee的指点,相比于常规的窗口程序开发,QT有着以下特点: 1. 优良的跨平台特性(支持Win.Linux.Mac 不同的平台下只需重新编译即可使用) 2. 面向 ...

  3. java命令执行jar文件

    如果java -jar target/hbase-demo-1.0-SNAPSHOT.jar HBaseDemo 提示如下 no main manifest attribute, in target/ ...

  4. rzsz安装【转】

    环境:CentOS 发生情况:需要安装工具:szrz 工具进行 windows 和linux传文件 安装方式:从网上其他教程找的所以就按照如下方式操作 1. 下载软件 rzsz-3.34.tar.gz ...

  5. C#中调用PowerShell代码

    在C#中调用PowerShell代码,很多时候Add是不好使的!要用AddScript!记录一下! using (Runspace runspace = RunspaceFactory.CreateR ...

  6. 成果展示-RSA算法工具

  7. C++笔记 3

    1.数组是自动分配空间,指针要手工分配空间(int *p = new int;) 2.在Unix上,程序出现段错误的时候,系统会生成core 文件,会把出现错误的那一刻的程序镜像保存在此文件中 3.结 ...

  8. 基于jQuery加入购物车飞入动画特效

    基于jQuery加入购物车飞入动画特效.这是一款电商购物网站常用的把商品加入购物车代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div id="main& ...

  9. python基础系列教程——Python中的编码问题,中文乱码问题

    python基础系列教程——Python中的编码问题,中文乱码问题 如果不声明编码,则中文会报错,即使是注释也会报错. # -*- coding: UTF-8 -*- 或者 #coding=utf-8 ...

  10. 汇编入门学习笔记 (九)—— call和ret

    疯狂的暑假学习之  汇编入门学习笔记 (九)--  call和ret 參考: <汇编语言> 王爽 第10章 call和ret都是转移指令. 1. ret和retf ret指令:用栈中的数据 ...