Java类的设计----多态性及其应用

多态性及其应用

多态性

多态—在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;
29     }
30 }

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=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 + "\nschool: "+ school;
13     }
15 }
16 class Graduate extends Student {
17     public String major="IT";
18     public String getInfo(){
20         return  "Name: "+ name + "\nage: "+ age + "\nschool: "+ school+"\nmajor:"+major;
22     }
23 }

对象类型转换 (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 }
时间: 2024-10-03 05:04:03

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

Java类的设计----Object 类

Object类 Object类是所有Java类的根父类如果在类的声明中未使用extends关键字指明其父类,则默认父类为Object类 public class Person { ... } 等价于: public class Person extends Object {. ... }例: method(Object obj){-}//可以接收任何类作为其参数 Object o=new Person; method(o); ==操作符与equals方法 ==操作符与equals方法的区别: =

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

访问控制 可以对Java类中定义的属性和方法进行访问控制----规定不同的保护等级: public.protected.default.private //仅在类的内部可以访问. private String email; //在同一个包内该属性可以被访问. String major; //在子类中该属性可以被访问, 且该子类可以跨包 protected int salary; //访问权限最高, 无论是否在一个包内, 无论是否是子类都可以被访问. public String name; 访问控

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

方法的重写.覆盖 在子类中可以根据需要对从父类中继承来的方法进行改造-覆盖方法(方法的重置.重写),在程序执行时,子类的方法将覆盖父类的方法. 覆盖方法必须和被覆盖方法具有相同的方法名称.参数列表和返回值类型. 覆盖方法不能使用比被覆盖方法更严格的访问权限. 覆盖方法举例(1) public class Person { public String name; public int age; public String getInfo() { return "Name: "+ name

java类的设计原则

1.内聚性 类应该描述一个单一的实体,所有的类操作应该在逻辑上相互配合,支持一个连贯性的目标.例如:学生和教职工属于不同的实体,应该定义两个类. 2.一致性 要遵循一定的设计风格和命名习惯.给类.方法.数据域选择有信息量的名字.流行的风格是将数据声明置于构造方法之前,并将构造方法置于方法之前. 选择的名字要保持一致,给类似的操作选择不同的名字并非好的习惯. 如果不想让用户创建类的对象,可以在类中声明一个私有的构造方法. 3.封装性 用private修饰符隐藏其数据域,以免用户直接访问.如果想让数

From C# to Java (2) - 类的设计 (1)

上一篇文章 From C# to Java (1) - 类型.引用与相等关系 对 Java 与 C# 在基本概念上的一些区别进行了简单的叙述,在这里简单做一回顾.第一,Java 的数据类型分为基础数据类型和类类型,类类型均为引用类型:第二,Java 的“==”运算符严格执行引用相等:第三,Java 不支持运算符重载.其中的很多重要特性在本文中也会提到,而且对类设计有重要的意义. 本文试图通过一个实际的 Java 类(Android Open Source Project 中的 BitmapFac

(转)Java 类的热替换 —— 概念、设计与实现

构建基于 Java 的在线升级系统 对于许多关键性业务或者庞大的 Java 系统来说,如果必须暂停系统服务才能进行系统升级,既会大大影响到系统的可用性,同时也增加了系统的管理和维护成本.因此,如果能够方便地在不停止系统业务的情况下进行系统升级,则可以很好地解决上述问题.在本文中,我们将基于实例,对构建在线升级 Java 系统的基础技术和设计原则进行了深入的讲解.相信读者能够根据文中的技术构建出自己的在线升级系统来. Java ClassLoader 技术剖析 在本文中,我们将不对 Java Cl

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

别人的一篇技术博客,直接摘抄过来,免得再查看找不到了(本人在看的过程中可能会对原文格式或文字有修改) 原文地址:http://blog.163.com/web_promise/blog/static/109631655201222804931240/ 在本文中,我们将不对 Java ClassLoader 的细节进行过于详细的讲解,而是关注于与构建在线升级系统相关的基础概念.关于 ClassLoader 的详细细节有许多资料可以参考,有兴趣的读者可以自行研读. 要构建在线升级系统,一个重要的技术

Java 类设计----Java类的继承

Java类的继承 为描述和处理个人信息,定义类Person: public class Person { public String name; public inat age; public Date birthDate; public String getInfo() {...}} 为描述和处理学生信息,定义类Student: public class Student { public String name; public int age; public Date birthDate; p

类的设计

1001: 类的设计(1) Time Limit: 1 Sec  Memory Limit: 65535 MB   64bit IO Format: %lldSubmitted: 9  Accepted: 7[Submit][Status][Web Board] Description 设计clock类,成员数据包含时(hour)分(minute)秒(second),都是int类型,根据给定的main函数设计必要的成员函数. main函数已给定,提交时只需要提交main函数外的代码部分. int