1. 程式人生 > >Java類的設計----多態性及其應用

Java類的設計----多態性及其應用

強制轉換 override enter -c ont 處理 shopping exce int

多態性及其應用

多態性

多態—在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 }

Java類的設計----多態性及其應用