• 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 + "
    " +"age: "+ age;
     6     }
     7 }
     8 class Student extends Person {
     9     protected String school="pku";
    10     public String getInfo() {
    11         return  "Name: "+ name + "
    age: "+ age + "
    school: "+ school;
    13     }
    15 }
    16 class Graduate extends Student {
    17     public String major="IT";
    18     public String getInfo(){
    20         return  "Name: "+ name + "
    age: "+ age + "
    school: "+ school+"
    major:"+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 + "
    " +"age: "+ age;
     6     }
     7 }
     8 class Student extends Person {
     9     protected String school="pku";
    10     public String getInfo() {
    11                 return  "Name: "+ name + "
    age: "+ age 
    12               + "
    school: "+ school;
    13     }
    14     
    15 }
    16 class Graduate extends Student{
    17     public String major="IT";
    18     public String getInfo()
    19     {
    20         return  "Name: "+ name + "
    age: "+ age 
    21               + "
    school: "+ school+"
    major:"+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("
    ");
    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 }
  • 相关阅读:
    奇异值分解(SVD)详解
    深度学习中常用的优化方法
    一年了,走了一些弯路,是时候回归了,介绍下深度学习中常见的降低过拟合的方法
    softmax与logistic关系
    Java [Leetcode 387]First Unique Character in a String
    Java [Leetcode 384]Shuffle an Array
    Java [Leetcode 167]Two Sum II
    用stack实现min stack
    bootstrap, boosting, bagging 几种方法的联系
    一道常被人轻视的前端JS面试题
  • 原文地址:https://www.cnblogs.com/justdoitba/p/7225531.html
Copyright © 2020-2023  润新知