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 }
Java類的設計----多態性及其應用