目錄
1.繼承的作用
2.繼承樹
3.protected和super
protected
?super
注:super/this()--構造方法,第一行,一般不同時出現
4.向上向下轉型
向上轉型
向下轉型
?final
小結
1.繼承的作用
????????理解:首先就是可以實現代碼復用,比如當我們讓Student繼承Person時, Student 就獲得了Person的所有功能。只需要給Student編寫新的功能(關鍵字extends)。
代碼部分如下:
class Person {private String name;private int age;public String getName() {...}public void setName(String name) {...}public int getAge() {...}public void setAge(int age) {...}
}class Student extends Person {// 不要重復name和age字段/方法,// 只需要定義新增score字段/方法:private int score;public int getScore() { … }public void setScore(int score) { … }
}
注意:
????????OOP術語中我們把Person稱為 超類(super class),父類(parent class),基類(base class, Student稱為子類(sub class).
2.繼承樹
????????一般來說,java中,父類沒有明確寫繼承的類,編譯器會自動加上extends object,所有的類最終的都會指向Object(Object沒有父類)。一個簡單的繼承樹如下圖所示:
┌───────────┐
│ Object │
└───────────┘▲│
┌───────────┐
│ Person │
└───────────┘▲│
┌───────────┐
│ Student │
└───────────┘如果在定義一個Teacher類繼承Person類,繼承樹如下:┌───────────┐│ Object │└───────────┘▲│┌───────────┐│ Person │└───────────┘▲ ▲│ ││ │
┌───────────┐ ┌───────────┐
│ Student │ │ Teacher │
└───────────┘ └───────────┘
3.protected和super
protected
理解(protect): 由于繼承就是子類無法訪問父類的private
字段或者private
方法,
為了讓子類可以訪問父類的字段,我們需要把private
改為protected
。用protected
修飾的字段可以被子類訪問:
class Person {protected String name;protected int age;
}class Student extends Person {public String hello() {return "Hello, " + name; // OK!}
}
protected
關鍵字可以把字段和方法的訪問權限控制在繼承樹內部,一個protected
字段和方法可以被其子類,以及子類的子類所訪問:
class Person {protected String name;protected int age;
}class Student extends Person {public String hello() {return "Hello, " + name; // OK!}
}
?super
super
關鍵字表示父類(超類)。子類引用父類的字段時,可以用super.fieldName。
class Student extends Person {public String hello() {return "Hello, " + super.name;}
}
public class Main {public static void main(String[] args) {Student s = new Student("Xiao Ming", 12, 89);}
}class Person {protected String name;protected int age;public Person(String name, int age) {this.name = name;this.age = age;}
}class Student extends Person {protected int score;public Student(String name, int age, int score) {this.score = score;}
}
? ? ? ?在Java
中,任何class
的構造方法,第一行語句必須是調用父類的構造方法。如果沒有明確地調用父類的構造方法,編譯器會幫我們自動加一句super()。
class Student extends Person {protected int score;public Student(String name, int age, int score) {super(); // 自動調用父類的構造方法this.score = score;}
}
注:super/this()--構造方法,第一行,一般不同時出現
?
4.向上向下轉型
向上轉型
Student s = new Student();
Person p = new Person();
// 引用類型為Person的變量指向Student類型的實例
Person p = new Student();
?????????Student
繼承自Person
,因此,它擁有Person
的全部功能。Person
類型的變量,如果指向Student
類型的實例,對它進行操作,是沒有問題的。這種把一個子類類型安全地變為父類類型的賦值,被稱為向上轉型(upcasting
)。
注:可以把Student類型轉型為Person,或者更高層次的Object。
向下轉型
和向上轉型相反,如果把一個父類類型強制轉型為子類類型,就是向下轉型(downcasting
)
Person p1 = new Student(); // upcasting, ok
Person p2 = new Person();
Student s1 = (Student) p1; // ok
Student s2 = (Student) p2; // runtime error! ClassCastException!
?????????運行時,Person
類型p1
實際指向Student
實例,Person
類型變量p2
實際指向Person
實例。在向下轉型的時候,把p1
轉型為Student
會成功,因為p1
確實指向Student
實例,把p2
轉型為Student
會失敗,由于p2
的實際類型是Person
,不能把父類變為子類,因為子類功能比父類多,多出的功能無法憑空變出來。因此,向下轉型很可能會失敗。失敗的時候,Java虛擬機會報ClassCastException
異常。
為了避免向下轉型出錯,Java
提供了instanceof
操作符,可以先判斷一個實例究竟是不是某種類型:
Person p = new Person();
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Student); // falseStudent s = new Student();
System.out.println(s instanceof Person); // true
System.out.println(s instanceof Student); // trueStudent n = null;
System.out.println(n instanceof Student); // false
?instanceof
實際上判斷一個變量所指向的實例是否是指定類型,或者這個類型的子類。如果一個引用變量為null
,那么對任何instanceof
的判斷都為false
。利用instanceof
,在向下轉型前可以先判斷:
Person p = new Student();
if (p instanceof Student) {// 只有判斷成功才會向下轉型:Student s = (Student) p; // 一定會成功
}
?final
-
// 類被final修飾,表示此類不能有子類,public final class Fu{
-
// final 修飾符基本數據類型變量-- 常量值不可變
-
// final 修飾符引用數據類型變量-- 地址不可變
-
// 當final修飾方法,表示此方法不能被重寫,但是final可被子類使用
小結
- 繼承是面向對象編程的一種強大的代碼復用方式
- Java只允許單繼承,所有類最終的根類是
Object
- 子類可以訪問訪問父類的
public
和protected
字段和方法 - 子類的構造方法可以通過
super()
調用父類的構造方法 - 當父類中不存在無參構造方法時,子類必須手動的調用父類的有參構造方法,并且必須在子類構造方法中的第一行
- 可以安全地向上轉型為更抽象的類型
- 向下轉型,可以使用
instanceof
運算符:用于判斷"引用指向的對象"是否是"指定類型",運算結果為boolean
類型 - 子類和父類的關系是
is
,has
關系不能用繼承